Core官方DI解析(4)--CallSiteRuntimeResolver
callsiteruntimeresolver
类型是一个创建或获取服务实例的类型,这个类型继承了callsitevisitor<targument, tresult>
这个类型,也是使用了访问者模式,下面一一来解析此类
serviceproviderenginescope
在解析`callsiteruntimeresolver`之前先看一下`serviceproviderenginescope`类型,这个类型就可以是一个容器类型,最后实例化的服务对象就缓存在此类之中, 从下面代码中可以看出此类实现了`iservicescope`和`iserviceprovider`两个接口,并且此类型拥有两个字段
_disposables:idisposabl集合,此字段缓存的时所有实现了idisposable接口的注册服务,以便在释放此容器实例时并将这些服务一起释放
_disposed:判断此属性是否已被是否释放
internal class serviceproviderenginescope : iservicescope, iserviceprovider { private list<idisposable> _disposables; private bool _disposed; }
在此类中还具有两个属性,一个是缓存实例对象的集合和一个**serviceproviderengine**类型的属性,从下面可以看出缓存集合使用了是`servicecachekey`作为缓存的key, 而engine是引擎类型,此属性通过构造函数传入,并且所有容器共享一个`serviceproviderengine`,也就是共享容器共享注册的服务
// 缓存的实例对象集合 internal dictionary<servicecachekey, object> resolvedservices { get; } = new dictionary<servicecachekey, object>(); // 所有serviceproviderenginescope对象共享一个serviceproviderengine public serviceproviderengine engine { get; } // 构造函数 public serviceproviderenginescope(serviceproviderengine engine)=> engine = engine;
这个类中一共具有四个方法,
- getservice():获取对象,可以看到此方法调用的engine的getservice(),这个方法到
serviceproviderengine
时再看- serviceprovider():这个方法返回的是当前对象
- dispose():释放当前容器,可以看到在释放当前容器时会把**_disposables集合中所有实例进行释放,并把_disposed**属性设置true
- capturedisposable():这个方法缓存要被的释放的服务实例
public object getservice(type servicetype) { if (_disposed) // 如果已被释放,就不能调用此方法 throwhelper.throwobjectdisposedexception(); return engine.getservice(servicetype, this); } public iserviceprovider serviceprovider => this; public void dispose() { lock (resolvedservices) { if (_disposed) return; _disposed = true; if (_disposables != null) { for (var i = _disposables.count - 1; i >= 0; i--) { var disposable = _disposables[i]; disposable.dispose(); } _disposables.clear(); } resolvedservices.clear(); } } // 缓存所有需要清理的服务实例 internal object capturedisposable(object service) { if (!referenceequals(this, service)) { if (service is idisposable disposable) { lock (resolvedservices) { if (_disposables == null) _disposables = new list<idisposable>(); _disposables.add(disposable); } } } return service; }
callsiteruntimeresolver
上面说过callsiteruntimeresolver
这个类型是创建和获取服务实例类型的访问者,这个类型泛型参数分别为runtimeresolvercontext
类型和实例对象类型object
internal sealed class callsiteruntimeresolver : callsitevisitor<runtimeresolvercontext, object>{}
runtimeresolvercontext
类型是一个serviceproviderenginescope
封装类型,这个类型中具有一个serviceproviderenginescope
类型属性和一个runtimeresolverlock
枚举类型属性,这个枚举类型在实例化对象时当做了锁使用
internal struct runtimeresolvercontext { public serviceproviderenginescope scope { get; set; } // 锁 public runtimeresolverlock acquiredlocks { get; set; } } [flags] internal enum runtimeresolverlock { scope = 1, root = 2 }
在callsiteruntimeresolver
类型中拥有两类方法,
- 根据注册服务的生命周期进行访问服务实例对象
- 根据servicecallsite的设置类型进行访问服务实例对象
这两个类都在其callsitevisitor<targument, tresult>
基类中
// 根据服务对象的生命周期进行访问访问实例 protected virtual tresult visitcallsite(servicecallsite callsite, targument argument) { // 缓存位置由servicecallsite内部的cache属性的location提供 switch (callsite.cache.location) { case callsiteresultcachelocation.root: return visitrootcache(callsite, argument); case callsiteresultcachelocation.scope: return visitscopecache(callsite, argument); case callsiteresultcachelocation.dispose: return visitdisposecache(callsite, argument); case callsiteresultcachelocation.none: return visitnocache(callsite, argument); default: throw new argumentoutofrangeexception(); } } // 根据其servicecallsite的kind属性访问服务对象 protected virtual tresult visitcallsitemain(servicecallsite callsite, targument argument) { switch (callsite.kind) { case callsitekind.factory: return visitfactory((factorycallsite)callsite, argument); case callsitekind.ienumerable: return visitienumerable((ienumerablecallsite)callsite, argument); case callsitekind.constructor: return visitconstructor((constructorcallsite)callsite, argument); case callsitekind.constant: return visitconstant((constantcallsite)callsite, argument); case callsitekind.serviceprovider: return visitserviceprovider((serviceprovidercallsite)callsite, argument); case callsitekind.servicescopefactory: return visitservicescopefactory((servicescopefactorycallsite)callsite, argument); default: throw new notsupportedexception($"call site type {callsite.gettype()} is not supported"); } }
这两个方法内部调用的方法部分被callsiteruntimeresolver
类中重写,
下面先来看看根据生命周期进行访问的一系列方法
-
vistrootcache:
这个方法是访问root生命周期的方法,可以看到这个在这个方法调用了一个visitcache(),这个方法一共四个参数,第一个,第二个分别是当前方法函数。第三个参数代表容器对象,容器使用的是
serviceproviderengine
实例中的root属性,这个容器代表了*容器,这也就是root生命周期的本质,使用的*容器进行创建/获取实例,第四个参数锁,此方法使用的是runtimeresolverlock.root锁 -
visitscopecache:
这个方法是访问scoped生命周期方法,此方法和上面方法相似,也是调用了visitcache(),但是不同的是是锁不同,这个锁是根据当前容器来决定,如果当前容器为*容器,就使用root锁,所以不为*容器,则使用scope锁
-
visitdisposecache
这个方法访问transient生命周期方法,可以看到这个方法直接调用visitcallsitemain()进行获取实例对象,然后调用capturedisposable()将此对象尝试缓存到serviceproviderenginescope容器的**_disposables**集合中
-
visitnocache
这个方法代表不缓存,这个方法在
callsiteruntimeresolver
类中未重写,所以直接调用的callsitevisitor
类型的visitnocache(),也基类中直接调用visitcallsitemain()
//// callsiteruntimeresolver // 访问root生命周期方法 protected override object visitrootcache(servicecallsite singletoncallsite, runtimeresolvercontext context) => visitcache(singletoncallsite, context, context.scope.engine.root, runtimeresolverlock.root); // 访问scoped生命周期方法 protected override object visitscopecache(servicecallsite singletoncallsite, runtimeresolvercontext context) { // 如果当前容器为根容器,则将其锁转换为root,否则为scope var requiredscope = context.scope == context.scope.engine.root ? runtimeresolverlock.root : runtimeresolverlock.scope; return visitcache(singletoncallsite, context, context.scope, requiredscope); } // 访问transient生命周期方法 protected override object visitdisposecache(servicecallsite transientcallsite, runtimeresolvercontext context) => context.scope.capturedisposable(visitcallsitemain(transientcallsite, context)); //// callsitevisitor // 无缓存 protected virtual tresult visitnocache(servicecallsite callsite, targument argument) => visitcallsitemain(callsite, argument);
**visitcache()**这个方法是使用指定的容器进行实例化并缓存服务实例对象,在下面代码中可以看到,代码中根据**runtimeresolvercontext**实例的枚举值与第四个参数进行,如果不相同,则进行加锁。然后进行获取实例服务对象,如果已缓存则直接获取,没有缓存则调用**visitcallsitemain()**获取实例并缓存
private object visitcache(servicecallsite scopedcallsite, runtimeresolvercontext context, serviceproviderenginescope serviceproviderengine, runtimeresolverlock locktype) { bool locktaken = false; // 获取容器中的缓存服务实例属性 var resolvedservices = serviceproviderengine.resolvedservices; if ((context.acquiredlocks & locktype) == 0) // 如果当前枚举值与runtimeresolvercontext的枚举值不相同,则加锁 monitor.enter(resolvedservices, ref locktaken); try { // 如果当前数据并未在缓存之中,则实例化此对象并将其缓存至集合中 if (!resolvedservices.trygetvalue(scopedcallsite.cache.key, out var resolved)) { // 获取实例对象 resolved = visitcallsitemain(scopedcallsite, new runtimeresolvercontext { scope = serviceproviderengine, acquiredlocks = context.acquiredlocks | locktype }); // 将当前对象尝试加入到容器的_disposables集合 serviceproviderengine.capturedisposable(resolved); // 缓存实例对象 resolvedservices.add(scopedcallsite.cache.key, resolved); } return resolved; } finally { if (locktaken) monitor.exit(resolvedservices); } }
**visitcallsitemain()**内调用的所有方法都在`callsiteruntimeresolver`类进行了重写,下面看看`callsiteruntimeresolve`类中的这些方法
-
visitfactory
在visitfactory()中直接调用了
factorycallsite
实例对象的工厂方法获取实例 -
visitienumerable
在visitienumerable()中实例了
ienumerablecallsite
中servicecallsites集合的所有对象,并组装到一个数组进行返回 -
constructorcallsite
在visitconstructor()中使用反射方法实例化对象,并且如果构造函数不为空则获取所有参数的实例对象
-
constantcallsite
在visitconstant()中直接返回了
constantcallsite
中的对象 -
visitserviceprovider
在visitserviceprovider()直接返回了
runtimeresolvercontext
封装的容器 -
visitservicescopefactory
在visitservicescopefactory()中则直接返回了容器实例中引擎对象(serviceproviderengine)
// factorycallsite protected override object visitfactory(factorycallsite factorycallsite, runtimeresolvercontext context) // 调用工厂方法进行实例化 => factorycallsite.factory(context.scope); // ienumerablecallsite protected override object visitienumerable(ienumerablecallsite enumerablecallsite, runtimeresolvercontext context) { var array = array.createinstance( enumerablecallsite.itemtype, enumerablecallsite.servicecallsites.length); for (var index = 0; index < enumerablecallsite.servicecallsites.length; index++) { // 实例化ienumerablecallsite.servicecallsites中所有的服务实例对象并赋值到数组中 var value = visitcallsite(enumerablecallsite.servicecallsites[index], context); array.setvalue(value, index); } return array; } // constructorcallsite protected override object visitconstructor(constructorcallsite constructorcallsite, runtimeresolvercontext context) { object[] parametervalues; if (constructorcallsite.parametercallsites.length == 0) parametervalues = array.empty<object>(); else { // 如果当前构造器参数不为空,则实例化每一个参数的实例对象 parametervalues = new object[constructorcallsite.parametercallsites.length]; for (var index = 0; index < parametervalues.length; index++) parametervalues[index] = visitcallsite(constructorcallsite.parametercallsites[index], context); } try { // 根据参数对象进行实例化对象并返回 return constructorcallsite.constructorinfo.invoke(parametervalues); } catch (exception ex) when (ex.innerexception != null) { exceptiondispatchinfo.capture(ex.innerexception).throw(); // the above line will always throw, but the compiler requires we throw explicitly. throw; } } // constantcallsite protected override object visitconstant(constantcallsite constantcallsite, runtimeresolvercontext context) // 直接返回constantcallsite的值 => constantcallsite.defaultvalue; // serviceprovidercallsite protected override object visitserviceprovider(serviceprovidercallsite serviceprovidercallsite, runtimeresolvercontext context) // 直接返回runtimeresolvercontext封装的容器 => context.scope; // servicescopefactorycallsite protected override object visitservicescopefactory(servicescopefactorycallsite servicescopefactorycallsite, runtimeresolvercontext context) // 直接返回容器内的serviceproviderengine => context.scope.engine;
在`callsiteruntimeresolver`中还有叫做**resolve()**,这个方法则是外部调用的,这个方法是由一个`servicecallsite`对象和一个容器对象`serviceproviderenginescope`,然后直接调用**visitcallsite()**进行方法,可以看到调用此方法时**acquiredlocks**属性并未赋值.
public object resolve(servicecallsite callsite, serviceproviderenginescope scope) { return visitcallsite(callsite, new runtimeresolvercontext { scope = scope }); }
上一篇: vmware的3种网络模式