• ASP.NET WebAPI 08 Message,HttpConfiguration,DependencyResolver


    ASP.NET WebAPI 08 Message,HttpConfiguration,DependencyResolver

     

    Message

    WebAPI作为通信架构必定包含包含请求与响应两个方法上的报文,在WebAPI它们分别是HttpRequestMessage,HttpResponseMessage。对于HttpResponseMessage之前在WebAPI返回结果中有应用。

    HttpRequestMessage

    请求报文包含请求地址(RequestUri),请求方法(Method),头信息(Headers),报文信息(Content)以及Http版本(Versions)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
        public class HttpRequestMessage : IDisposable
        {
            public HttpRequestMessage();       
            public HttpRequestMessage(HttpMethod method, string requestUri);       
            public HttpRequestMessage(HttpMethod method, Uri requestUri);
            public HttpContent Content { getset; }       
            public HttpRequestHeaders Headers { get; }    
            public HttpMethod Method { getset; }      
            public IDictionary<stringobject> Properties { get; }       
            public Uri RequestUri { getset; }       
            public Version Version { getset; }
            public void Dispose();       
            protected virtual void Dispose(bool disposing);      
            public override string ToString();
    }

    另外,WebAPI提供了一个类型为IDictionary<string,object>的属性Properties。我们可以将做任意对象作为附加属性添加到HttpRequestMessage.

    HttpResponseMessage

    请求报文包含状态码(StatusCode),原因短句(ReasonPhrase),头信息(Headers),报文信息(Content)以及Http版本(Versions)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
        public class HttpRequestMessage : IDisposable
        {
            public HttpRequestMessage();       
            public HttpRequestMessage(HttpMethod method, string requestUri);       
            public HttpRequestMessage(HttpMethod method, Uri requestUri);
            public HttpContent Content { getset; }       
            public HttpRequestHeaders Headers { get; }    
            public HttpMethod Method { getset; }      
            public IDictionary<stringobject> Properties { get; }       
            public Uri RequestUri { getset; }       
            public Version Version { getset; }
            public void Dispose();       
            protected virtual void Dispose(bool disposing);      
            public override string ToString();
    }

    HttpConfiguration

    HttpConfiguration在WebAPI大概有如下几个作用:

    1. 设置通信管道
    2. 存储全局信息(比如Filter,Route,Formatter)
    3. 提供一个Ioc架构,用于WebAPI的扩展
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    public class HttpConfiguration : IDisposable
    {
        public HttpConfiguration();
        public HttpConfiguration(HttpRouteCollection routes);
        public IDependencyResolver DependencyResolver { getset; }
        public HttpFilterCollection Filters { get; }
        public MediaTypeFormatterCollection Formatters { get; }
        public IncludeErrorDetailPolicy IncludeErrorDetailPolicy { getset; }
        public Action<HttpConfiguration> Initializer { getset; }
        public Collection<System.Net.Http.DelegatingHandler> MessageHandlers { get; }
        public ParameterBindingRulesCollection ParameterBindingRules { getinternal set; }
        public ConcurrentDictionary<objectobject> Properties { get; }
        public HttpRouteCollection Routes { get; }
        public ServicesContainer Services { getinternal set; }
        public string VirtualPathRoot { get; }
        public void Dispose();
        protected virtual void Dispose(bool disposing);
        public void EnsureInitialized();
    }

    对于第1 点我们在每6篇已经用到。第2点后面会陆续讲到,本篇只重点讲下第3点。这一功能主要是通过ServicesContainer来完成,即HttpConfiguration中的Services属性。

    WebAPI对ServicesContainer的提供的派生类是DefaultServices,在DefaultServices,包含了两种依赖注入方法:1,单一派生类型注入(multi),2,多派生类型注入(single),即在注入派生类型的数量有区别。比如在获取url参数的时候有QueryString,RouteData两种方式,而这两种方式是通过QueryStringValueProvider与RouteDataValueProvider两种类型来实现的(实际在DefaultServices注入是这人两个类对应的Factory类),这两种类型属于平行关系,所以这个时候能需要采用multi方法注入。

    这些类型都是在DefaultServces的构造中注入的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
        public class DefaultServices : ServicesContainer
        {
            protected DefaultServices();
            public DefaultServices(HttpConfiguration configuration);
            protected override void ClearSingle(Type serviceType);
            public override object GetService(Type serviceType);
            protected override List<object> GetServiceInstances(Type serviceType);
            public override IEnumerable<object> GetServices(Type serviceType);
            public override bool IsSingleService(Type serviceType);
            protected override void ReplaceSingle(Type serviceType, object service);
            protected override void ResetCache(Type serviceType);
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
        public abstract class ServicesContainer : IDisposable
        {
            protected ServicesContainer();
            public void Add(Type serviceType, object service);
            public void AddRange(Type serviceType, IEnumerable<object> services);
            public virtual void Clear(Type serviceType);
            public virtual void Dispose();
            public int FindIndex(Type serviceType, Predicate<object> match);
            public abstract object GetService(Type serviceType);
            public abstract IEnumerable<object> GetServices(Type serviceType);
            public void Insert(Type serviceType, int index, object service);
    viceType, int index, IEnumerable<object> services);
            public abstract bool IsSingleService(Type serviceType);
            public bool Remove(Type serviceType, object service);
            public int RemoveAll(Type serviceType, Predicate<object> match);
            public void RemoveAt(Type serviceType, int index);
            public void Replace(Type serviceType, object service);
            public void ReplaceRange(Type serviceType, IEnumerable<object> services);
        }

    ServicesContainer只提供的了替换与获取的公共方法。因为ServicesContainer只提供了WebAPI中的标准组件,并不想作为一个公共的Ioc容器,而这些标准的组件是WebAPI进行扩展的基础。

    下面我写的四个Action分别是获取所有multiServices,获取所有singleServices,向multiServices中添加一个自定义的ValueProviderFactory,向singleServices中添加自定义的IExceptionHandler.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    public Dictionary<Type, List<Type>> GetAllMultiServices()
    {
        Dictionary<Type, List<Type>> result = new Dictionary<Type, List<Type>>();
        FieldInfo field = RequestContext.Configuration.Services.GetType().GetField("_defaultServicesMulti",
            BindingFlags.NonPublic|BindingFlags.Instance);
        Dictionary<Type, List<object>> multiServices = (Dictionary<Type, List<object>>)field.GetValue(RequestContext.Configuration.Services);
        foreach (var in multiServices)
        {
            List<Type> items = new List<Type>();
            foreach (var item in s.Value) {
                items.Add(item.GetType());
            }
            result[s.Key] = items;
        }
        return result;
    }
     
    public Dictionary<Type, Type> GetAllSingleServices()
    {
        Dictionary<Type, Type> result = new Dictionary<Type, Type>();
        FieldInfo field = RequestContext.Configuration.Services.GetType().GetField("_defaultServicesSingle",
            BindingFlags.NonPublic | BindingFlags.Instance);
        Dictionary<Type, object> services = (Dictionary<Type, object>)field.GetValue(RequestContext.Configuration.Services);
        foreach (var in services)
        {
             
            result.Add(s.Key, s.Value==null?null:s.Value.GetType());
        }
        return result;
    }
     
    public Dictionary<Type, List<Type>> AddMultiService()
    {
        List<ValueProviderFactory> valueProviderFactories=new List<ValueProviderFactory>(){
        new QueryStringValueProviderFactory(),
        new RouteDataValueProviderFactory(),
        new MyValueProviderFactory()
        };
        RequestContext.Configuration.Services.ReplaceRange(typeof(ValueProviderFactory), valueProviderFactories);
        return GetAllMultiServices();
    }
     
    public Dictionary<Type, Type> ReplaceSingleService()
    {
        RequestContext.Configuration.Services.Replace(typeof(IExceptionHandler), new MyExceptionHandler());
        return GetAllSingleServices();
    }

    因为ServicesContainer中的类型注入都是固定的,所以WebAPI给ServicesContainer扩展了一组获取Service的方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    public static class ServicesExtensions
    {
        public static IHttpActionInvoker GetActionInvoker(this ServicesContainer services);
        public static IHttpActionSelector GetActionSelector(this ServicesContainer services);
        public static IActionValueBinder GetActionValueBinder(this ServicesContainer services);
        public static IApiExplorer GetApiExplorer(this ServicesContainer services);
        public static IAssembliesResolver GetAssembliesResolver(this ServicesContainer services);
        public static IBodyModelValidator GetBodyModelValidator(this ServicesContainer services);
        public static IContentNegotiator GetContentNegotiator(this ServicesContainer services);
        public static IDocumentationProvider GetDocumentationProvider(this ServicesContainer services);
        public static IExceptionHandler GetExceptionHandler(this ServicesContainer services);
        public static IEnumerable<IExceptionLogger> GetExceptionLoggers(this ServicesContainer services);
        public static IEnumerable<System.Web.Http.Filters.IFilterProvider> GetFilterProviders(this ServicesContainer services);
        public static IHostBufferPolicySelector GetHostBufferPolicySelector(this ServicesContainer services);
        public static IHttpControllerActivator GetHttpControllerActivator(this ServicesContainer services);
        public static IHttpControllerSelector GetHttpControllerSelector(this ServicesContainer services);
        public static IHttpControllerTypeResolver GetHttpControllerTypeResolver(this ServicesContainer services);
        public static IEnumerable<System.Web.Http.ModelBinding.ModelBinderProvider> GetModelBinderProviders(this ServicesContainer services);
        public static ModelMetadataProvider GetModelMetadataProvider(this ServicesContainer services);
        public static IEnumerable<ModelValidatorProvider> GetModelValidatorProviders(this ServicesContainer services);
        public static ITraceManager GetTraceManager(this ServicesContainer services);
        public static ITraceWriter GetTraceWriter(this ServicesContainer services);
        public static IEnumerable<System.Web.Http.ValueProviders.ValueProviderFactory> GetValueProviderFactories(this ServicesContainer services);
    }

    在ASP.NET WebAPI中有一个GlobalConfiguration,其实它并不是WebAPI的一部分。WebAPI只是一个独立的框架。它需要寄宿在别的应用程序下才能运行。寄宿模式则分为两种WebHost,SelfHost,WebHost是针对Web程序的寄宿。因为本系列只讨论ASP.Net下的WebAPI,所以只简单讲一下WebHost模式。

    ASP.NET WebAPI中引用了程序集System.Web.Http.WebHost,GlobalConfiguration就在该程序集下.它包含了一个HttpConfiguration属性.还一个配置HttpConfiguration的方法

    另外还有一个HttServer

    另外在ApiController的很多属性都能找到HttpConfiguraiton
    Configuration

    ControllerContext.Configuration

    RequestContext.Configuration

    这些HttpConfiguration都来自对GlobalConfiguration.Configuration的引用.

    DependencyResolver

    WebAPI为我们提供了一个Ioc框架,即DependencyResolver

       

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    public interface IDependencyResolver : IDependencyScope, IDisposable
     
     {
     
    IDependencyScope BeginScope();
     
     }
     
    public interface IDependencyScope : IDisposable
     
     {
     
    object GetService(Type serviceType);
     
    IEnumerable<object> GetServices(Type serviceType);
     
     }

    IDependencyResolver也继承了IDependencyScope,所以我们可以将IDependencyScope视为依赖的上下文.

    在WebAPI中DependencyResolver并没有像其它组件一样注册在ServicesContainer中,而是直接注册在HttpConfiguration中(DependencyResolver属性).

    别个HttpRequestMessage中也有一扩展方法GetDependencyScope来获取DependencyScope,该方法获取的是HttpRequestMessage的Properties的DependencyResolver,这里的DependencyResolver也来自HttpConfiguration.

    在WebAPI中也定义了一个EmptyResolver,它只是一个空的Resolver,所以在WebAPI默认就是采用直接反射方式.

    源码

    Github: https://github.com/BarlowDu/WebAPI (API_8)

  • 相关阅读:
    老陈与小石头运算代码
    第五次作业
    老陈与小石头
    简易四则运算
    四则运算
    对git的认识
    第一次作业
    arcgis-tomcat-cors
    jquery deferred promise
    springloaded hot deploy
  • 原文地址:https://www.cnblogs.com/shiningrise/p/5585927.html
Copyright © 2020-2023  润新知