• ASP.NET Web API 框架研究 Controller创建 HttpController 类型解析 选择 创建


       上一篇介绍了HttpController的一些细节,接下来说下HttpController 类型解析、选择和创建。生产HttpController实例的生产线如下图:

      

    一、涉及的类及源码分析

      涉及的类主要在程序集System.Web.Http中的Dispatcher下边,类如下图:

      

    1、IAssembliesResolver DefaultAssembliesResolver

      AssembliesResolver为HttpController类型的解析提供了可选的程序集,即提供了实现了IHttpController接口的候选HttpController类型的程序集范围;所有AssembliesResolver都实现IAssembliesResolver,接口只有一个方法,如下

      public interface IAssembliesResolver
        {
            //提供解析的程序集范围,返回应用程序可用的程序集列表
            ICollection<Assembly> GetAssemblies();
        }

      默认实现是DefauItAssembliesResolver,DefauItAssembliesResolver在实现的GetAssembIies方法中直接返回当前应用程序域加载的所有程序集列表,代码如下

      public class DefaultAssembliesResolver : IAssembliesResolver
        {
            public virtual ICollection<Assembly> GetAssemblies()
            {
                return AppDomain.CurrentDomain.GetAssemblies().ToList();
            }
        }

      而服务接口IAssembliesResolver的服务实例DefauItAssembliesResolver,是在服务容器里注册的

      获取可以用扩展方法直接获取:

      

     

     2、IHttpControllerTypeResolver DefaultHttpControllerTypeResolver

       返回可供选择的HttpControllerType列表。

      前边的AssembIiesResolver对象为HttpController类型的解析提供了可供选择的程序集,而HttpControllerTypeResolver具体进行类型解析,其均实现了接口IHttpControllerTypeResolver,其只有一个方法GetControllerTypes,而且以IAssembIiesResolver为参数,提供类型程序集。如下:

       public interface IHttpControllerTypeResolver
        {
            //参数IAssembliesResolver提供解析的程序集
            ICollection<Type> GetControllerTypes(IAssembliesResolver assembliesResolver);
        }

      即根据提供的程序集参数,获取所有符合条件的HttpControllerType列表,现在还没解析完,后续还要从其中选择一个合适的,只是返回可供选择的列表,默认实现是DefaultHttpControllerTypeResolver。

      注意点:

    • 委托 Predicate<Type>,Func<Assembly, Type[]>这种函数式编程用法,把函数当属性和参数
    • 只是从多个指定程序集中返回可供选择的HttpControllerType列表,还不是最后解析出的类型
    • 判断HttpController类型有效规则,即外部可见 (IsVisibIe=true)的实例 (IsAbstract=false)类 (IsClass=true),直接或耆间接实现了接口IHttpController,类型名称必须以“Controller” 为后缀,但是不区分大小写 (即 可以使用 “controIler” 作为后缀 )。
    public class DefaultHttpControllerTypeResolver : IHttpControllerTypeResolver
        {
            //判断是否为有效Controller的委托,默认指定了IsControllerType,也可以在构造函数指定
            private readonly Predicate<Type> _isControllerTypePredicate;
            //从程序集获取Type[]的委托,可以直接属性设置
            private Func<Assembly, Type[]> _getTypesFunc = GetTypes;
    
    
            //构造函数,可以指定一个委托来判断是不是控制器类型,默认使用下边的IsControllerType
            public DefaultHttpControllerTypeResolver()
                : this(IsControllerType)
            {
            }
    
            //构造函数,可以指定一个委托来判断是不是控制器类型
            public DefaultHttpControllerTypeResolver(Predicate<Type> predicate)
            {
                if (predicate == null)
                {
                    throw Error.ArgumentNull("predicate");
                }
    
                _isControllerTypePredicate = predicate;
            }
    
            //只读,否为有效Controller的委托
            protected internal virtual Predicate<Type> IsControllerTypePredicate
            {
                get { return _isControllerTypePredicate; }
            }
    
            //默认的用来判断是否是控制器的委托predicate
            internal static bool IsControllerType(Type t)
            {
                Contract.Assert(t != null);
                return
                    t != null &&
                    t.IsClass &&
                    t.IsVisible &&
                    !t.IsAbstract &&
                    typeof(IHttpController).IsAssignableFrom(t) &&
                    HasValidControllerName(t);
            }
    
           
            //返回可用的控制器列表
            public virtual ICollection<Type> GetControllerTypes(IAssembliesResolver assembliesResolver)
            {
                if (assembliesResolver == null)
                {
                    throw Error.ArgumentNull("assembliesResolver");
                }
    
                List<Type> result = new List<Type>();
    
                // 从assembliesResolver获取所有程序集
                ICollection<Assembly> assemblies = assembliesResolver.GetAssemblies();
                //遍历每个程序集
                foreach (Assembly assembly in assemblies)
                {
                    Type[] exportedTypes = null;
                    if (assembly == null || assembly.IsDynamic)
                    {
                        // 空或动态程序集就继续下个程序集,不操作当前程序集
                        continue;
                    }
    
                    try
                    {
                        //从程序集中获取Type[]
                        exportedTypes = _getTypesFunc(assembly);
                    }
                    catch (ReflectionTypeLoadException ex)
                    {
                        exportedTypes = ex.Types;
                    }
                    catch
                    {
                        //忽略异常,继续解析,不影响最后结果,除非找不到NOT FOUND
                        continue;
                    }
    
                    if (exportedTypes != null)
                    {
                        //从Type[]中把有效的ControllerType存放到结果列表中
                        result.AddRange(exportedTypes.Where(x => TypeIsVisible(x) && IsControllerTypePredicate(x)));
                    }
                }
    
                return result;
            }
    
            //默认使用的从程序集获取Type[]
            internal static Type[] GetTypes(Assembly assembly)
            {
                return assembly.GetTypes();
            }
    
            // 要以Controller结尾,但不能就是Controller,因为路由解析的控制器也不会为空
            internal static bool HasValidControllerName(Type controllerType)
            {
                Contract.Assert(controllerType != null);
                string controllerSuffix = DefaultHttpControllerSelector.ControllerSuffix;
                return controllerType.Name.Length > controllerSuffix.Length && controllerType.Name.EndsWith(controllerSuffix, StringComparison.OrdinalIgnoreCase);
            }
    
            //设置从程序集获取Type[]的委托
            internal void SetGetTypesFunc(Func<Assembly, Type[]> getTypesFunc)
            {
                _getTypesFunc = getTypesFunc;
            }
    
            private static bool TypeIsVisible(Type type)
            {
                //IsVisible是不是可以由程序集代码外访问
                return (type != null && type.IsVisible);
            }
        }

      

      其也可以通过ServicesContainer扩展方法直接获取:

      

    3、HttpControllerTypeCache

      用来缓存反射出来的HttpControllerType,提高性能,是对HttpControllerTypeResolver解析出来的HttpController类型列表的缓存。

      缓存是一个Dictionary<string, ILookup<string, Type>>字典类型,Key为去除Controller后的部分,不区分大小写,如ProductController,Key为"Producct",Value为一个 ILookup<string, Type>类型,其Key可以重复,Key为控制器所在的命名空间,如ProductController所在命名空间"MyNameSpace",Value为具体的控制器类型如"ProductController"。

      注意:

      相同名称的控制器可能存在不同程序集和不同命名空间下

    internal sealed class HttpControllerTypeCache
        {
            private readonly HttpConfiguration _configuration;
            //惰性加载,缓存,Key为控制器名称出去Controller的部分(不区分大小写),
            //Value为一个ILookup<string, Type>,其Key可以重复,为控制所在的命名空间,Value为对应的控制器类型
            //相同名称的控制器可能存在不同程序集和不同命名空间下
            private readonly Lazy<Dictionary<string, ILookup<string, Type>>> _cache;
    
            public HttpControllerTypeCache(HttpConfiguration configuration)
            {
                if (configuration == null)
                {
                    throw Error.ArgumentNull("configuration");
                }
    
                _configuration = configuration;
                _cache = new Lazy<Dictionary<string, ILookup<string, Type>>>(InitializeCache);
            }
    
            //由于使用Lazy,调用该属性时候,才调用下边的InitializeCache
            internal Dictionary<string, ILookup<string, Type>> Cache
            {
                get { return _cache.Value; }
            }
    
            //根据控制器名称获取可选的ControllerType列表,从缓存读取
            public ICollection<Type> GetControllerTypes(string controllerName)
            {
                if (String.IsNullOrEmpty(controllerName))
                {
                    throw Error.ArgumentNullOrEmpty("controllerName");
                }
    
                HashSet<Type> matchingTypes = new HashSet<Type>();
    
                ILookup<string, Type> namespaceLookup;
                if (_cache.Value.TryGetValue(controllerName, out namespaceLookup))
                {
                    foreach (var namespaceGroup in namespaceLookup)
                    {
                        matchingTypes.UnionWith(namespaceGroup);
                    }
                }
    
                return matchingTypes;
            }
    
            //初始化缓存
            private Dictionary<string, ILookup<string, Type>> InitializeCache()
            {
                //获取AssembliesResolver服务实例
                IAssembliesResolver assembliesResolver = _configuration.Services.GetAssembliesResolver();
                //获取ControllersResolver服务实例
                IHttpControllerTypeResolver controllersResolver = _configuration.Services.GetHttpControllerTypeResolver();
                //调用ControllersResolver.GetControllerTypes以assembliesResolver为参数获取ControllerType列表
                ICollection<Type> controllerTypes = controllersResolver.GetControllerTypes(assembliesResolver);
                //先对解析出来的ControllerType列表按照ControllerType去除Controller后的名称分组,不区分大小写(OrdinalIgnoreCase)
                var groupedByName = controllerTypes.GroupBy(
                    t => t.Name.Substring(0, t.Name.Length - DefaultHttpControllerSelector.ControllerSuffix.Length),
                    StringComparer.OrdinalIgnoreCase);
                //再转换成Dictionary<string, ILookup<string, Type>>缓存结构
                return groupedByName.ToDictionary(
                    g => g.Key,
                    g => g.ToLookup(t => t.Namespace ?? String.Empty, StringComparer.OrdinalIgnoreCase),
                    StringComparer.OrdinalIgnoreCase);
            }
        }

     4、IHttpControllerSelector DefaultHttpControllerSelector

      HttpControllerTypeResolver只是解析出所有合法的ControllerType列表,接下来要根据请求选择出匹配的HttpController类型。

      通过HttpControllerSelector来完成,其都实现接口IHttpControllerSelector,其主要有两个方法,如下:

     public interface IHttpControllerSelector
        {
            //根据请求选择一个匹配的控制器对应的描述符
            HttpControllerDescriptor SelectController(HttpRequestMessage request);
    
            //返回描述所有HttpController类型的HttpControllerDescriptor对象与对应的HttpController名称之间的映射夫系
            IDictionary<string, HttpControllerDescriptor> GetControllerMapping();
        }

      同前边,默认实现DefaultHttpControllerSelector,也是是在服务容器里注册的,且同

      

      

      主要逻辑:

    • 控制器名称获取,不管Web Host还是Self Host路由解析数据最后都是放在HttpRequestMessage的属性字典中,所以先从请求中获取路由数据,再得到controller名称。如果路由变量中不存在名为controller的数据,或者程序集不存在或存在多个ControllerType,都会抛出异常
    • 丢弃在不同命名空间有多个匹配结果的控制器,比如,对于product名称的控制器,在A名称空间和B命名空间都有ProductController,由于系统不知道激活哪一个,所以采用的策略是两个都丢弃。这个逻辑在方法GetControllerMapping()
    • 系统会对GetControllerMapping结果缓存,我们在HttpControllerTypeResolver阶段解析出来的ControllerType在不同命名空间中存在多个匹配的控制器,所以采用Dictionary<string, ILookup<string, Type>>缓存,而GetControllerMapping返回的是IDictionary<string, HttpControllerDescriptor>类型,会丢弃上一点中的重复的控制器,返回的都是唯一的结果
    • 有两个缓存结构,一个是HttpControllerTypeCache 存放了所有合法的ControllerType,另一个是Lazy<ConcurrentDictionary<string, HttpControllerDescriptor>> _controllerInfoCache,它是根据前者构建出来的
    • 编程技巧,使用Lazy,Lazy<ConcurrentDictionary<string, HttpControllerDescriptor>> _controllerInfoCache,在从缓存_controllerInfoCache里读取数据时候,才去构建缓存内容,详细见代码注释
    public class DefaultHttpControllerSelector : IHttpControllerSelector
        {
            public static readonly string ControllerSuffix = "Controller";
    
            private const string ControllerKey = "controller";
    
            private readonly HttpConfiguration _configuration;
            //ControllerType缓存
            private readonly HttpControllerTypeCache _controllerTypeCache;
            private readonly Lazy<ConcurrentDictionary<string, HttpControllerDescriptor>> _controllerInfoCache;
    
            public DefaultHttpControllerSelector(HttpConfiguration configuration)
            {
                if (configuration == null)
                {
                    throw Error.ArgumentNull("configuration");
                }
                //Lazy惰性加载,用到_controllerInfoCache时候才去执行InitializeControllerInfoCache,进行缓存数据构建
                _controllerInfoCache = new Lazy<ConcurrentDictionary<string, HttpControllerDescriptor>>(InitializeControllerInfoCache);
                _configuration = configuration;
                _controllerTypeCache = new HttpControllerTypeCache(_configuration);
            }
    
            //从请求中匹配指定控制器名称的控制器描述符号,从缓存中读取,缓存构建时机是在读取缓存时候,使用Lazy实现
            public virtual HttpControllerDescriptor SelectController(HttpRequestMessage request)
            {
                if (request == null)
                {
                    throw Error.ArgumentNull("request");
                }
    
                IHttpRouteData routeData = request.GetRouteData();
                HttpControllerDescriptor controllerDescriptor;
                if (routeData != null)
                {
                    //先按特性路由(以后再说)解析,如果解析出数据,就直接返回
                    controllerDescriptor = GetDirectRouteController(routeData);
                    if (controllerDescriptor != null)
                    {
                        return controllerDescriptor;
                    }
                }
                //非特性路由则
                //从HttpRequestMessage属性字典中获取控制器名称,获取不到就NotFound
                string controllerName = GetControllerName(request);
                if (String.IsNullOrEmpty(controllerName))
                {
                    throw new HttpResponseException(request.CreateErrorResponse(
                        HttpStatusCode.NotFound,
                        Error.Format(SRResources.ResourceNotFound, request.RequestUri),
                        Error.Format(SRResources.ControllerNameNotFound, request.RequestUri)));
                }
                //从控制器描述符缓存中获取,找到就直接返回,在此Lazy惰性加载,才去执行InitializeControllerInfoCache,进行缓存数据构建
                if (_controllerInfoCache.Value.TryGetValue(controllerName, out controllerDescriptor))
                {
                    return controllerDescriptor;
                }
    
                //找不到就根据实际情况,抛出不同异常
                ICollection<Type> matchingTypes = _controllerTypeCache.GetControllerTypes(controllerName);
    
                // ControllerInfoCache is already initialized.
                Contract.Assert(matchingTypes.Count != 1);
                //根据不同原因创建不同类型异常
                if (matchingTypes.Count == 0)
                {
                    // 没有匹配
                    throw new HttpResponseException(request.CreateErrorResponse(
                        HttpStatusCode.NotFound,
                        Error.Format(SRResources.ResourceNotFound, request.RequestUri),
                        Error.Format(SRResources.DefaultControllerFactory_ControllerNameNotFound, controllerName)));
                }
                else
                {
                    // 匹配多个类型
                    throw CreateAmbiguousControllerException(request.GetRouteData().Route, controllerName, matchingTypes);
                }
            }
    
            public virtual IDictionary<string, HttpControllerDescriptor> GetControllerMapping()
            {
                return _controllerInfoCache.Value.ToDictionary(c => c.Key, c => c.Value, StringComparer.OrdinalIgnoreCase);
            }
    
            //从HttpRequestMessage的属性字典中获取控制器名称
            public virtual string GetControllerName(HttpRequestMessage request)
            {
                if (request == null)
                {
                    throw Error.ArgumentNull("request");
                }
                //先从HttpRequestMessage的属性字典中获取路由数据
                IHttpRouteData routeData = request.GetRouteData();
                if (routeData == null)
                {
                    return null;
                }
    
                // TryGetValue获取key为controller的路由变量值
                string controllerName = null;
                routeData.Values.TryGetValue(ControllerKey, out controllerName);
                return controllerName;
            }
    
            //特性路由逻辑以后再说
            private static HttpControllerDescriptor GetDirectRouteController(IHttpRouteData routeData)
            {
                CandidateAction[] candidates = routeData.GetDirectRouteCandidates();
                if (candidates != null)
                {
                    // Set the controller descriptor for the first action descriptor
                    Contract.Assert(candidates.Length > 0);
                    Contract.Assert(candidates[0].ActionDescriptor != null);
    
                    HttpControllerDescriptor controllerDescriptor = candidates[0].ActionDescriptor.ControllerDescriptor;
    
                    // Check that all other candidate action descriptors share the same controller descriptor
                    for (int i = 1; i < candidates.Length; i++)
                    {
                        CandidateAction candidate = candidates[i];
                        if (candidate.ActionDescriptor.ControllerDescriptor != controllerDescriptor)
                        {
                            // We've found an ambiguity (multiple controllers matched)
                            throw CreateDirectRouteAmbiguousControllerException(candidates);
                        }
                    }
    
                    return controllerDescriptor;
                }
    
                return null;
            }
    
            private static Exception CreateDirectRouteAmbiguousControllerException(CandidateAction[] candidates)
            {
                Contract.Assert(candidates != null);
                Contract.Assert(candidates.Length > 1);
    
                HashSet<Type> matchingTypes = new HashSet<Type>();
                for (int i = 0; i < candidates.Length; i++)
                {
                    matchingTypes.Add(candidates[i].ActionDescriptor.ControllerDescriptor.ControllerType);
                }
    
                // we need to generate an exception containing all the controller types
                StringBuilder typeList = new StringBuilder();
                foreach (Type matchedType in matchingTypes)
                {
                    typeList.AppendLine();
                    typeList.Append(matchedType.FullName);
                }
    
                return Error.InvalidOperation(SRResources.DirectRoute_AmbiguousController, typeList, Environment.NewLine);
            }
    
            private static Exception CreateAmbiguousControllerException(IHttpRoute route, string controllerName, ICollection<Type> matchingTypes)
            {
                Contract.Assert(route != null);
                Contract.Assert(controllerName != null);
                Contract.Assert(matchingTypes != null);
    
                // Generate an exception containing all the controller types
                StringBuilder typeList = new StringBuilder();
                foreach (Type matchedType in matchingTypes)
                {
                    typeList.AppendLine();
                    typeList.Append(matchedType.FullName);
                }
    
                string errorMessage = Error.Format(SRResources.DefaultControllerFactory_ControllerNameAmbiguous_WithRouteTemplate, controllerName, route.RouteTemplate, typeList, Environment.NewLine);
                return new InvalidOperationException(errorMessage);
            }
    
            //初始化构建ConcurrentDictionary<string, HttpControllerDescriptor>缓存,根据Dictionary<string, ILookup<string, Type>>类型 列表缓存
            private ConcurrentDictionary<string, HttpControllerDescriptor> InitializeControllerInfoCache()
            {
                var result = new ConcurrentDictionary<string, HttpControllerDescriptor>(StringComparer.OrdinalIgnoreCase);
                //由于同一控制器名称在不同命名空间中存在多个控制器类型,所以要去掉重复的,用来记录重复的Key
                var duplicateControllers = new HashSet<string>();
                //先从控制器类型列表中缓存中获取控制器类型列表
                Dictionary<string, ILookup<string, Type>> controllerTypeGroups = _controllerTypeCache.Cache;
    
                //遍历
                foreach (KeyValuePair<string, ILookup<string, Type>> controllerTypeGroup in controllerTypeGroups)
                {
                    string controllerName = controllerTypeGroup.Key;
    
                    foreach (IGrouping<string, Type> controllerTypesGroupedByNs in controllerTypeGroup.Value)
                    {
                        foreach (Type controllerType in controllerTypesGroupedByNs)
                        {
                            if (result.Keys.Contains(controllerName))
                            {
                                //有重复就记录在重复集合里,待移除处理
                                duplicateControllers.Add(controllerName);
                                break;
                            }
                            else
                            {
                                //new  HttpControllerDescriptor
                                result.TryAdd(controllerName, new HttpControllerDescriptor(_configuration, controllerName, controllerType));
                            }
                        }
                    }
                }
                //去掉有重复的匹配控制器的数据
                foreach (string duplicateController in duplicateControllers)
                {
                    HttpControllerDescriptor descriptor;
                    result.TryRemove(duplicateController, out descriptor);
                }
    
                return result;
            }
        }

     5、IHttpControllerActivator DefaultHttpControllerActivator

      通过HttpControllerTypeResolver解析得到请求(controller名称)对应的控制器描述符(HttpControllerDescriptor)后,通过HttpControllerActivator根据控制器描述符最终创建出HttpController实例,其都实现接口IHttpControllerActivator ,其定义如下:

      public interface IHttpControllerActivator
        {
            //根据HttpControllerDescriptor创建出IHttpController
            IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType);
        }

      DefaultHttpControllerActivator是默认实现,其配置同前边几个,不再赘述

      主要逻辑:

    • 在Create方法中,如果dependency resolver可以解析返回,就直接返回,否则就用创建委托activator来执行创建,而创建委托activator可以缓存到本地缓存和controllerDescriptor.Properties cache缓存,由上一篇可以知道,默认的IoC容器是EmptyResolver,所以dependency resolver都是返回空,所以每次都是通过反射创建实例。
    • activator通过反射来创建,在第一点中缓存的是创建对象的委托,而不是HttpController实例,其每次都是重新创建,所以对于多个针对相同的HttpControlIer类型的请求来说,最终创建的HttpController实例都是不同的
     public class DefaultHttpControllerActivator : IHttpControllerActivator
        {
            //缓存HttpControllerDescriptor对应的创建委托
            private Tuple<HttpControllerDescriptor, Func<IHttpController>> _fastCache;
            private object _cacheKey = new object();
    
            //核心创建方法,如果dependency resolver可以解析返回,就直接返回,否则就用创建委托activator来执行创建,
            //而创建委托activator可以缓存到本地缓存和controllerDescriptor.Properties cache缓存
            public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
            {
                if (request == null)
                {
                    throw Error.ArgumentNull("request");
                }
    
                if (controllerDescriptor == null)
                {
                    throw Error.ArgumentNull("controllerDescriptor");
                }
    
                if (controllerType == null)
                {
                    throw Error.ArgumentNull("controllerType");
                }
    
                try
                {
                    Func<IHttpController> activator;
    
                    //如果没有定义本地快速缓存
                    if (_fastCache == null)
                    {
                        IHttpController controller = GetInstanceOrActivator(request, controllerType, out activator);
                        if (controller != null)
                        {
                            //这里返回的是dependency resolver中有定义时候,定义的Controller实例
                            return controller;
                        }
                        else
                        {
                            //初始化创建一个本地缓存cacheItem
                            Tuple<HttpControllerDescriptor, Func<IHttpController>> cacheItem = Tuple.Create(controllerDescriptor, activator);
                            Interlocked.CompareExchange(ref _fastCache, cacheItem, null);
                        }
                    }
                    else if (_fastCache.Item1 == controllerDescriptor)
                    {
                        // 如果有定义本地快速缓存,而且匹配controllerDescriptor key就直接返回
                        activator = _fastCache.Item2;
                    }
                    else
                    {
                        // 如果有定义本地快速缓存,没有匹配controllerDescriptor key,就从controllerDescriptor.Properties cache中获取创建委托
                        object value;
                        if (controllerDescriptor.Properties.TryGetValue(_cacheKey, out value))
                        {
                            activator = (Func<IHttpController>)value;
                        }
                        else
                        {
                            IHttpController controller = GetInstanceOrActivator(request, controllerType, out activator);
                            if (controller != null)
                            {
                                //这里返回的是dependency resolver中有定义时候,定义的Controller实例
                                return controller;
                            }
                            else
                            {
                                //添加进HttpControllerDescriptor.Properties cache
                                controllerDescriptor.Properties.TryAdd(_cacheKey, activator);
                            }
                        }
                    }
                    //执行创建委托,创建实例
                    return activator();
                }
                catch (Exception ex)
                {
                    throw Error.InvalidOperation(ex, SRResources.DefaultControllerFactory_ErrorCreatingController, controllerType.Name);
                }
            }
    
            // 返回控制器实例如果在dependency resolver得到就直接返回,否则通过反射创建
            private static IHttpController GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, out Func<IHttpController> activator)
            {
                Contract.Assert(request != null);
                Contract.Assert(controllerType != null);
    
                // 如果dependency resolver可以直接返回controller就直接返回使用
                IHttpController instance = (IHttpController)request.GetDependencyScope().GetService(controllerType);
                if (instance != null)
                {
                    activator = null;
                    return instance;
                }
    
                //如果dependency resolver没有定义,就返回通过反射直接创建的委托
                activator = TypeActivator.Create<IHttpController>(controllerType);
                return null;
            }
        }

     二、自定义扩展组件HttpControllerActivator

      从前边IHttpControllerActivator那节知道,每次创建实例都是通过反射完成的,因为默认情况下的IoC容器是EmptyResolver,所以dependency resolver都是返回空,根据代码可以知道,都是通过反射来完成,我们可以通过重新实现IHttpControllerActivator,把服务容器里默认定义的DefaultHttpControllerActivator替换掉,替换掉EmptyResolver的方式,上一篇已经说过。

       public class UnityHttpControllerActivator : IHttpControllerActivator
        {
            public IUnityContainer UnityContainer { get; private set; }
    
            public UnityHttpControllerActivator(IUnityContainer unityContainer)
            {
                this.UnityContainer = unityContainer;
            }
    
            public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
            {
                return (IHttpController)this.UnityContainer.Resolve(controllerType);
            }
        }

      注册:

     UnityContainer unityContainer = new UnityContainer();
     GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator),new UnityHttpControllerActivator(unityContainer));
  • 相关阅读:
    Oracle根据两点经纬度计算距离(转载)
    TCP小见解
    git describe功能实现
    UE中基本图形的原始大小是多大
    SQL多行合并与HTML组装,不转义特殊字符
    磁盘空间不足引起ftp报"553 Could not create file"
    一键安装包安装lnmp
    宝塔面板(Linux版)安装与使用
    Redhat7-yum本地源安装配置
    Oracle数据库多个表空间使用情况查询
  • 原文地址:https://www.cnblogs.com/shawnhu/p/8067955.html
Copyright © 2020-2023  润新知