ASP.NET WebAPI 08 Message,HttpConfiguration,DependencyResolver

13568 ワード

Message


WebAPIは、通信アーキテクチャとして、それぞれHttpRequestMessage、HttpResponseMessageである要求と応答の2つの方法上のメッセージを含むに違いない.HttpResponseMessageについては、WebAPIからの返信結果に適用されます.

HttpRequestMessage


要求メッセージには、要求アドレス(RequestUri)、要求メソッド(Method)、ヘッダ情報(Headers)、メッセージ情報(Content)、およびHttpバージョン(Versions)が含まれる
 
    public class HttpRequestMessage : IDisposable
    {
        public HttpRequestMessage();        
        public HttpRequestMessage(HttpMethod method, string requestUri);        
        public HttpRequestMessage(HttpMethod method, Uri requestUri);
        public HttpContent Content { get; set; }        
        public HttpRequestHeaders Headers { get; }     
        public HttpMethod Method { get; set; }       
        public IDictionary<string, object> Properties { get; }        
        public Uri RequestUri { get; set; }        
        public Version Version { get; set; }
        public void Dispose();        
        protected virtual void Dispose(bool disposing);       
        public override string ToString();
}

 
 
 
さらに、WebAPIは、IDictionaryのタイプの属性Propertiesを提供する.任意のオブジェクトを付加的な属性としてHttpRequestMessageに追加することができます.
 

HttpResponseMessage


要求メッセージには、ステータスコード(StatusCode)、理由短文(ReasonPhrase)、ヘッダ情報(Headers)、メッセージ情報(Content)、およびHttpバージョン(Versions)が含まれます.
 
    public class HttpRequestMessage : IDisposable
    {
        public HttpRequestMessage();        
        public HttpRequestMessage(HttpMethod method, string requestUri);        
        public HttpRequestMessage(HttpMethod method, Uri requestUri);
        public HttpContent Content { get; set; }        
        public HttpRequestHeaders Headers { get; }     
        public HttpMethod Method { get; set; }       
        public IDictionary<string, object> Properties { get; }        
        public Uri RequestUri { get; set; }        
        public Version Version { get; set; }
        public void Dispose();        
        protected virtual void Dispose(bool disposing);       
        public override string ToString();
}

 
 
 
 
 

HttpConfiguration


HttpConfigurationはWebAPIで次のような役割を果たしています.

  • 通信パイプの設定

  • Filter,Route,Formatterなどのグローバル情報を格納

  • WebAPIの拡張のためのIocアーキテクチャを提供

  •  
     
        public class HttpConfiguration : IDisposable
        {
            public HttpConfiguration();
            public HttpConfiguration(HttpRouteCollection routes); 
            public IDependencyResolver DependencyResolver { get; set; }
            public HttpFilterCollection Filters { get; }
            public MediaTypeFormatterCollection Formatters { get; }
            public IncludeErrorDetailPolicy IncludeErrorDetailPolicy { get; set; }
            public Action<HttpConfiguration> Initializer { get; set; }
            public Collection<System.Net.Http.DelegatingHandler> MessageHandlers { get; }
            public ParameterBindingRulesCollection ParameterBindingRules { get; internal set; }
            public ConcurrentDictionary<object, object> Properties { get; }
            public HttpRouteCollection Routes { get; }
            public ServicesContainer Services { get; internal set; }
            public string VirtualPathRoot { get; }
            public void Dispose();
            protected virtual void Dispose(bool disposing); 
            public void EnsureInitialized();
        }
    

     
     
     
    第1点については6編ごとに使用しています.2点目以降では、本編では3点目に重点を置いています.この機能は主に、HttpConfigurationのServicesプロパティであるServicesContainerによって実行されます.
    WebAPIがServicesContainerに提供する派生クラスはDefaultServicesであり、DefaultServicesでは、1、単一派生タイプ注入(multi)、2、マルチ派生タイプ注入(single)、すなわち注入派生タイプの数に違いがある2つの依存注入方法が含まれている.例えばurlパラメータを取得する場合にはQueryString,RouteDataの2つの方式があるが,この2つの方式はQueryStringValueProviderとRouteDataValueProviderの2つのタイプで実現されている(実際にはDefaultServices注入はこの人の2つのクラスに対応するFactoryクラスである).この2つのタイプは平行関係に属するので,この場合multiメソッドで注入する必要がある.
     
     
    これらのタイプは、DefaultServicesの構造に注入されます.
     
        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);
    }
    

     
     
        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の拡張の基礎である.
    以下に私が書いた4つのアクションはそれぞれすべてのmultiServicesを取得し、すべてのsingleServicesを取得し、multiServicesにカスタムのValueProviderFactoryを追加し、singleServicesにカスタムのIExceptionHandlerを追加することです.
     
            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 s 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 s 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にサービスを取得する方法のセットを拡張しました.
     
        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は独立したフレームワークにすぎません.実行するには、別のアプリケーションの下にホストする必要があります.ホストモードは2つのWebHost,SelfHost,WebHostに分けられ,Webプログラムに対するホストである.本シリーズはASPのみを扱っているため.Net下のWebAPIなので、WebHostモードだけを簡単に説明します.
    ASP.NET WebAPIでは、プログラムセットSystemが参照する.Web.Http.WebHost、GlobalConfigurationはこのプログラムセットの下にあります.HttpConfigurationプロパティが含まれています.HttpConfigurationを構成するもう一つの方法
    もう一つHttServer
     
    またApiControllerの多くの属性でH t p C o n f i g u raitonConfigurationを見つけることができます
    ControllerContext.Configuration
    RequestContext.Configuration
     
    これらのHttpConfigurationはすべてGlobalConfigurationから来ている.Configurationの引用
     
     

    DependencyResolver


    WebAPIは、DependencyResolverというIocフレームワークを提供しています.
       
    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にも、HttpRequestMessageのPropertiesのDependencyResolverを取得する拡張メソッドGetDependencyScopeがある、ここのDependencyResolverもHttpConfigurationから来ている.
    WebAPIにもEmptyResolverが定義されているが、それは空のResolverであるため、WebAPIではデフォルトでは直接反射方式が採用されている.
     

    ソースコード


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