ASP.NET Core Controller与IOC结合问题整理(2)

用过上面的源码可知,真正创建Controller的地方在_controllerActivator.Create方法中,通过上面的源码可知为IControllerActivator默认注册的是DefaultControllerActivator类,直接找到源码位置[点击查看源码],我们继续简化一下源码如下所示

internal class DefaultControllerActivator : IControllerActivator { private readonly ITypeActivatorCache _typeActivatorCache; public DefaultControllerActivator(ITypeActivatorCache typeActivatorCache) { _typeActivatorCache = typeActivatorCache; } /// <summary> /// Controller实例的创建方法 /// </summary> public object Create(ControllerContext controllerContext) { //获取Controller类型信息 var controllerTypeInfo = controllerContext.ActionDescriptor.ControllerTypeInfo; //获取ServiceProvider var serviceProvider = controllerContext.HttpContext.RequestServices; //创建controller实例 return _typeActivatorCache.CreateInstance<object>(serviceProvider, controllerTypeInfo.AsType()); } /// <summary> /// 释放Controller实例 /// </summary> public void Release(ControllerContext context, object controller) { //如果controller实现了IDisposable接口,那么Release的时候会自动调用Controller的Dispose方法 //如果我们在Controller中存在需要释放或者关闭的操作,可以再Controller的Dispose方法中统一释放 if (controller is IDisposable disposable) { disposable.Dispose(); } } }

通过上面的代码我们依然要继续深入到ITypeActivatorCache实现中去寻找答案,通过查看MvcCoreServiceCollectionExtensions类的AddMvcCoreServices方法源码我们可以找到如下信息

services.TryAddSingleton<ITypeActivatorCache, TypeActivatorCache>();

有了这个信息,我们可以直接找到TypeActivatorCache类的源码[点击查看源码]代码并不多,大致如下所示

internal class TypeActivatorCache : ITypeActivatorCache { //创建ObjectFactory的委托 private readonly Func<Type, ObjectFactory> _createFactory = (type) => ActivatorUtilities.CreateFactory(type, Type.EmptyTypes); //Controller类型和对应创建Controller实例的ObjectFactory实例的缓存 private readonly ConcurrentDictionary<Type, ObjectFactory> _typeActivatorCache = new ConcurrentDictionary<Type, ObjectFactory>(); /// <summary> /// 真正创建实例的地方 /// </summary> public TInstance CreateInstance<TInstance>( IServiceProvider serviceProvider, Type implementationType) { //真正创建的操作是createFactory //通过Controller类型在ConcurrentDictionary缓存中获得ObjectFactory //而ObjectFactory实例由ActivatorUtilities.CreateFactory方法创建的 var createFactory = _typeActivatorCache.GetOrAdd(implementationType, _createFactory); //返回创建实例 return (TInstance)createFactory(serviceProvider, arguments: null); } }

通过上面类的代码我们可以清晰的得出一个结论,默认情况下Controller实例是由ObjectFactory创建出来的,而ObjectFactory实例是由ActivatorUtilities的CreateFactory创建出来,所以Controller实例每次都是由ObjectFactory创建而来,并非注册到IOC容器中。并且我们还可以得到一个结论ObjectFactory应该是一个委托,我们找到ObjectFactory定义的地方[点击查看源码]

delegate object ObjectFactory(IServiceProvider serviceProvider, object[] arguments);

这个确实如我们猜想的那般,这个委托会通过IServiceProvider实例去构建类型的实例,通过上述源码相关的描述我们会产生一个疑问,既然Controller实例并非由IOC容器托管,它由ObjectFactory创建而来,但是ObjectFactory实例又是由ActivatorUtilities构建的,那么生产对象的核心也就在ActivatorUtilities类中,接下来我们就来探究一下ActivatorUtilities的神秘面纱。

ActivatorUtilities类的探究

书接上面,我们知道了ActivatorUtilities类是创建Controller实例最底层的地方,那么ActivatorUtilities到底和容器是啥关系,因为我们看到了ActivatorUtilities创建实例需要依赖ServiceProvider,一切都要从找到ActivatorUtilities类的源码开始。我们最初接触这个类的地方在于它通过CreateFactory方法创建了ObjectFactory实例,那么我们就从这个地方开始,找到源码位置[]实现如下

public static ObjectFactory CreateFactory(Type instanceType, Type[] argumentTypes) { //查找instanceType的构造函数 //找到构造信息ConstructorInfo //得到给定类型与查找类型instanceType构造函数的映射关系 FindApplicableConstructor(instanceType, argumentTypes, out ConstructorInfo constructor, out int?[] parameterMap); //构建IServiceProvider类型参数 var provider = Expression.Parameter(typeof(IServiceProvider), "provider"); //构建给定类型参数数组参数 var argumentArray = Expression.Parameter(typeof(object[]), "argumentArray"); //通过构造信息、构造参数对应关系、容器和给定类型构建表达式树Body var factoryExpressionBody = BuildFactoryExpression(constructor, parameterMap, provider, argumentArray); //构建lambda var factoryLamda = Expression.Lambda<Func<IServiceProvider, object[], object>>( factoryExpressionBody, provider, argumentArray); var result = factoryLamda.Compile(); //返回执行结果 return result.Invoke; }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/bf1ee1456570f5337e46cd2c59e470f6.html