ASP.NET Web API 框架研究 服务容器 ServicesContainer
ServicesContainer是一个服务的容器,可以理解为—个轻量级的IoC容器,其维护着一个服务接口类型与服务实例之间的映射关系,可以根据服务接口类型获取对应的服务实例。构成ASP.NET Web API核心框架的消息处理管道的每个环节都注册了相应的组件来完成某项独立的任务,这些 “标准化 ”的组件—般都实现了某个预定义的接口,如果这些原生的组件不能满足我们的需求,我们完全可以通过实现相应的接口创建自定义的组件,然后以某种形式将它们 “注册安装 ”到消息处理管道上。
ASP.NET Web API的 配置都是通过HttpConfiguration来完成的,自定义 “服务实例 ”的注册也是由它来完成,有一个类 型为 ServicesContainer的只读属性Sewice,默认使用的 ServicesContainer是 一个类型为 Defaultservices的对象.
一、涉及的类和源码分析
1、ServicesContainer
抽象类,用IEnumerable<object>或List<object>及其子类存放服务实例集合,具体用哪种类型由其子类来决定。提供了对服务类型的服务实例的添加,删除,查询,覆盖,查找,还有可以标记是否是单服务实例,如GetService,GetServices,Add,FindIndex,Replace等方法,公开了几个抽象接口,如下边的抽象方法,由子类实现。
- public abstract class ServicesContainer : IDisposable
- {
- internal readonly Lazy<IExceptionLogger> ExceptionServicesLogger;
- internal readonly Lazy<IExceptionHandler> ExceptionServicesHandler;
- protected ServicesContainer()
- {
- ExceptionServicesLogger = new Lazy<IExceptionLogger>(CreateExceptionServicesLogger);
- ExceptionServicesHandler = new Lazy<IExceptionHandler>(CreateExceptionServicesHandler);
- }
- //抽象方法,获取某个接口类型对应的实例类型
- public abstract object GetService(Type serviceType);
- //抽象方法,获取某个接口类型的对应的多个实例类型
- public abstract IEnumerable<object> GetServices(Type serviceType);
- //抽象方法,获取某个接口类型的对应的多个实例类型
- protected abstract List<object> GetServiceInstances(Type serviceType);
- //虚方法清空某个服务类型的缓存
- protected virtual void ResetCache(Type serviceType)
- {
- }
- //服务类型是单实例还是多实例
- public abstract bool IsSingleService(Type serviceType);
- //往某个服务接口的服务实例列表末尾添加一个服务实例
- public void Add(Type serviceType, object service)
- {
- Insert(serviceType, Int32.MaxValue, service);
- }
- //往某个服务接口的服务实例列表末尾添加多个服务实例
- public void AddRange(Type serviceType, IEnumerable<object> services)
- {
- InsertRange(serviceType, Int32.MaxValue, services);
- }
- //移除服务类型的所有服务实例,分单实例和多实例情况
- public virtual void Clear(Type serviceType)
- {
- if (serviceType == null)
- {
- throw Error.ArgumentNull("serviceType");
- }
- if (IsSingleService(serviceType))
- {
- ClearSingle(serviceType);
- }
- else
- {
- ClearMultiple(serviceType);
- }
- ResetCache(serviceType);
- }
- //抽象方法,清除单实例
- protected abstract void ClearSingle(Type serviceType);
- //清除多实例
- protected virtual void ClearMultiple(Type serviceType)
- {
- List<object> instances = GetServiceInstances(serviceType);
- instances.Clear();
- }
- //根据匹配的委托查找符合条件的第一个索引位置(从0开始),找不到就返回-1
- public int FindIndex(Type serviceType, Predicate<object> match)
- {
- if (serviceType == null)
- {
- throw Error.ArgumentNull("serviceType");
- }
- if (match == null)
- {
- throw Error.ArgumentNull("match");
- }
- List<object> instances = GetServiceInstances(serviceType);
- return instances.FindIndex(match);
- }
- //在服务类型的服务实例集合的指定索引位置(0开始)插入一个服务实例
- public void Insert(Type serviceType, int index, object service)
- {
- if (serviceType == null)
- {
- throw Error.ArgumentNull("serviceType");
- }
- if (service == null)
- {
- throw Error.ArgumentNull("service");
- }
- if (!serviceType.IsAssignableFrom(service.GetType()))
- {
- throw Error.Argument("service", SRResources.Common_TypeMustDriveFromType, service.GetType().Name, serviceType.Name);
- }
- List<object> instances = GetServiceInstances(serviceType);
- if (index == Int32.MaxValue)
- {
- index = instances.Count;
- }
- instances.Insert(index, service);
- ResetCache(serviceType);
- }
- //在服务类型的服务实例集合的指定索引位置(0开始)插入多个服务实例
- public void InsertRange(Type serviceType, int index, IEnumerable<object> services)
- {
- if (serviceType == null)
- {
- throw Error.ArgumentNull("serviceType");
- }
- if (services == null)
- {
- throw Error.ArgumentNull("services");
- }
- object[] filteredServices = services.Where(svc => svc != null).ToArray();
- object incorrectlyTypedService = filteredServices.FirstOrDefault(svc => !serviceType.IsAssignableFrom(svc.GetType()));
- if (incorrectlyTypedService != null)
- {
- throw Error.Argument("services", SRResources.Common_TypeMustDriveFromType, incorrectlyTypedService.GetType().Name, serviceType.Name);
- }
- List<object> instances = GetServiceInstances(serviceType);
- if (index == Int32.MaxValue)
- {
- index = instances.Count;
- }
- instances.InsertRange(index, filteredServices);
- ResetCache(serviceType);
- }
- //从服务类型的服务实例列表中移除指定的服务实例
- public bool Remove(Type serviceType, object service)
- {
- if (serviceType == null)
- {
- throw Error.ArgumentNull("serviceType");
- }
- if (service == null)
- {
- throw Error.ArgumentNull("service");
- }
- List<object> instances = GetServiceInstances(serviceType);
- bool result = instances.Remove(service);
- ResetCache(serviceType);
- return result;
- }
- //移除某个服务类型的所有委托匹配的服务实例元素
- public int RemoveAll(Type serviceType, Predicate<object> match)
- {
- if (serviceType == null)
- {
- throw Error.ArgumentNull("serviceType");
- }
- if (match == null)
- {
- throw Error.ArgumentNull("match");
- }
- List<object> instances = GetServiceInstances(serviceType);
- int result = instances.RemoveAll(match);
- ResetCache(serviceType);
- return result;
- }
- //移除某个服务类型的服务实例集合的指定索引的服务实例
- public void RemoveAt(Type serviceType, int index)
- {
- if (serviceType == null)
- {
- throw Error.ArgumentNull("serviceType");
- }
- List<object> instances = GetServiceInstances(serviceType);
- instances.RemoveAt(index);
- ResetCache(serviceType);
- }
- //用某个服务实例替换某个服务类型所有的服务实例
- public void Replace(Type serviceType, object service)
- {
- // 更早的空检查,不需要在插入之前就调用RemoveAll,而导致空服务异常
- if (serviceType == null)
- {
- throw Error.ArgumentNull("serviceType");
- }
- if ((service != null) && (!serviceType.IsAssignableFrom(service.GetType())))
- {
- throw Error.Argument("service", SRResources.Common_TypeMustDriveFromType, service.GetType().Name, serviceType.Name);
- }
- if (IsSingleService(serviceType))
- {
- ReplaceSingle(serviceType, service);
- }
- else
- {
- ReplaceMultiple(serviceType, service);
- }
- ResetCache(serviceType);
- }
- //抽象方法,替换单个实例
- protected abstract void ReplaceSingle(Type serviceType, object service);
- protected virtual void ReplaceMultiple(Type serviceType, object service)
- {
- //先移除所有,再在头部插入
- RemoveAll(serviceType, _ => true);
- Insert(serviceType, , service);
- }
- //用多个服务实例替换某个服务类型所有的服务实例
- public void ReplaceRange(Type serviceType, IEnumerable<object> services)
- {
- if (services == null)
- {
- throw Error.ArgumentNull("services");
- }
- RemoveAll(serviceType, _ => true);
- InsertRange(serviceType, , services);
- }
- //资源回收空实现,子类重写
- public virtual void Dispose()
- {
- }
- private IExceptionLogger CreateExceptionServicesLogger()
- {
- return ExceptionServices.CreateLogger(this);
- }
- private IExceptionHandler CreateExceptionServicesHandler()
- {
- return ExceptionServices.CreateHandler(this);
- }
- }
2、DefaultServices
继承自ServicesContainer,是默认实现,在HttpConfiguration里指定,构造函数中注册一些默认的实例,注意点:
- 使用到了IDependencyResolver进行DI操作获取实例
- 使用了缓存提高性能,ConcurrentDictionary
另外,两个核心方法逻辑
- GetService,重写方法,根据服务类型获取单个服务实例,缓存里有就从缓存里,否则把DI解析,如果有就返回,否则从字典里获取返回,并添加进缓存
- GetServices,重写方法,根据服务类型获取服务实例列表,缓存里有就从缓存里,否则把DI解析的和字典里的一起返回,,并添加进缓存
- public class DefaultServices : ServicesContainer
- {
- //缓存
- private ConcurrentDictionary<Type, object[]> _cacheMulti = new ConcurrentDictionary<Type, object[]>();
- private ConcurrentDictionary<Type, object> _cacheSingle = new ConcurrentDictionary<Type, object>();
- private readonly HttpConfiguration _configuration;
- //服务实例存放集合
- private readonly Dictionary<Type, object> _defaultServicesSingle = new Dictionary<Type, object>();
- private readonly Dictionary<Type, List<object>> _defaultServicesMulti = new Dictionary<Type, List<object>>();
- //通过它来
- private IDependencyResolver _lastKnownDependencyResolver;
- private readonly HashSet<Type> _serviceTypesSingle;
- private readonly HashSet<Type> _serviceTypesMulti;
- /// <summary>
- /// This constructor is for unit testing purposes only.
- /// </summary>
- protected DefaultServices()
- {
- }
- private void SetSingle<T>(T instance) where T : class
- {
- _defaultServicesSingle[typeof(T)] = instance;
- }
- private void SetMultiple<T>(params T[] instances) where T : class
- {
- var x = (IEnumerable<object>)instances;
- _defaultServicesMulti[typeof(T)] = new List<object>(x);
- }
- public DefaultServices(HttpConfiguration configuration)
- {
- if (configuration == null)
- {
- throw Error.ArgumentNull("configuration");
- }
- _configuration = configuration;
- //初始化注册服务类型的服务实例,即使是空的,获得空会抛异常
- SetSingle<IActionValueBinder>(new DefaultActionValueBinder());
- SetSingle<IApiExplorer>(new ApiExplorer(configuration));
- SetSingle<IAssembliesResolver>(new DefaultAssembliesResolver());
- SetSingle<IBodyModelValidator>(new DefaultBodyModelValidator());
- SetSingle<IContentNegotiator>(new DefaultContentNegotiator());
- SetSingle<IDocumentationProvider>(null); // Missing
- SetMultiple<IFilterProvider>(new ConfigurationFilterProvider(),
- new ActionDescriptorFilterProvider());
- SetSingle<IHostBufferPolicySelector>(null);
- SetSingle<IHttpActionInvoker>(new ApiControllerActionInvoker());
- SetSingle<IHttpActionSelector>(new ApiControllerActionSelector());
- SetSingle<IHttpControllerActivator>(new DefaultHttpControllerActivator());
- SetSingle<IHttpControllerSelector>(new DefaultHttpControllerSelector(configuration));
- SetSingle<IHttpControllerTypeResolver>(new DefaultHttpControllerTypeResolver());
- SetSingle<ITraceManager>(new TraceManager());
- SetSingle<ITraceWriter>(null);
- // This is a priority list. So put the most common binders at the top.
- SetMultiple<ModelBinderProvider>(new TypeConverterModelBinderProvider(),
- new TypeMatchModelBinderProvider(),
- new KeyValuePairModelBinderProvider(),
- new ComplexModelDtoModelBinderProvider(),
- new ArrayModelBinderProvider(),
- new DictionaryModelBinderProvider(),
- new CollectionModelBinderProvider(),
- new MutableObjectModelBinderProvider());
- SetSingle<ModelMetadataProvider>(new DataAnnotationsModelMetadataProvider());
- SetMultiple<ModelValidatorProvider>(new DataAnnotationsModelValidatorProvider(),
- new DataMemberModelValidatorProvider());
- // This is an ordered list,so put the most common providers at the top.
- SetMultiple<ValueProviderFactory>(new QueryStringValueProviderFactory(),
- new RouteDataValueProviderFactory());
- ModelValidatorCache validatorCache = new ModelValidatorCache(new Lazy<IEnumerable<ModelValidatorProvider>>(() => this.GetModelValidatorProviders()));
- SetSingle<IModelValidatorCache>(validatorCache);
- SetSingle<IExceptionHandler>(new DefaultExceptionHandler());
- SetMultiple<IExceptionLogger>();
- _serviceTypesSingle = new HashSet<Type>(_defaultServicesSingle.Keys);
- _serviceTypesMulti = new HashSet<Type>(_defaultServicesMulti.Keys);
- // Reset the caches and the known dependency scope
- ResetCache();
- }
- public override bool IsSingleService(Type serviceType)
- {
- if (serviceType == null)
- {
- throw Error.ArgumentNull("serviceType");
- }
- return _serviceTypesSingle.Contains(serviceType);
- }
- //重写方法,根据服务类型获取单个服务实例,缓存里有就从缓存里,否则把DI解析,如果有就返回,否则从字典里获取返回,并添加进缓存
- public override object GetService(Type serviceType)
- {
- // 为空直接抛出异常,提高性能
- if (serviceType == null)
- {
- throw Error.ArgumentNull("serviceType");
- }
- // 如果DependencyResolver改变了,缓存里解析的变为无效,要清空
- if (_lastKnownDependencyResolver != _configuration.DependencyResolver)
- {
- ResetCache();
- }
- object result;
- //在缓存里直接返回
- if (_cacheSingle.TryGetValue(serviceType, out result))
- {
- return result;
- }
- // Check input after initial read attempt for performance.
- if (!_serviceTypesSingle.Contains(serviceType))
- {
- throw Error.Argument("serviceType", SRResources.DefaultServices_InvalidServiceType, serviceType.Name);
- }
- //从DI获取服务实例,为了不实例化多次,放到缓存
- object dependencyService = _lastKnownDependencyResolver.GetService(serviceType);
- //不在缓存里(肯定不在),添加到缓存,并设置结果
- if (!_cacheSingle.TryGetValue(serviceType, out result))
- {
- //如果DI获取到,就用它,否则就从字典中获取
- result = dependencyService ?? _defaultServicesSingle[serviceType];
- _cacheSingle.TryAdd(serviceType, result);
- }
- return result;
- }
- //重写方法,根据服务类型获取服务实例列表,缓存里有就从缓存里,否则把DI解析的和字典里的一起返回,,并添加进缓存
- public override IEnumerable<object> GetServices(Type serviceType)
- {
- // 为空直接抛出异常,提高性能
- if (serviceType == null)
- {
- throw Error.ArgumentNull("serviceType");
- }
- // 如果DependencyResolver改变了,缓存里解析的变为无效,要清空
- if (_lastKnownDependencyResolver != _configuration.DependencyResolver)
- {
- ResetCache();
- }
- object[] result;
- if (_cacheMulti.TryGetValue(serviceType, out result))
- {
- return result;
- }
- // Check input after initial read attempt for performance.
- if (!_serviceTypesMulti.Contains(serviceType))
- {
- throw Error.Argument("serviceType", SRResources.DefaultServices_InvalidServiceType, serviceType.Name);
- }
- //从DI获取服务实例,为了不实例化多次,放到缓存
- IEnumerable<object> dependencyServices = _lastKnownDependencyResolver.GetServices(serviceType);
- //不在缓存里(肯定不在),添加到缓存,并设置结果
- if (!_cacheMulti.TryGetValue(serviceType, out result))
- {
- //把DI中获取的和字典中获取的一起放到结果中
- result = dependencyServices.Where(s => s != null)
- .Concat(_defaultServicesMulti[serviceType])
- .ToArray();
- _cacheMulti.TryAdd(serviceType, result);
- }
- return result;
- }
- //重写方法,返回某个服务类型的所有服务实例
- protected override List<object> GetServiceInstances(Type serviceType)
- {
- Contract.Assert(serviceType != null);
- List<object> result;
- if (!_defaultServicesMulti.TryGetValue(serviceType, out result))
- {
- throw Error.Argument("serviceType", SRResources.DefaultServices_InvalidServiceType, serviceType.Name);
- }
- return result;
- }
- //重写方法,清除单个
- protected override void ClearSingle(Type serviceType)
- {
- _defaultServicesSingle[serviceType] = null;
- }
- //重写方法 替换某个
- protected override void ReplaceSingle(Type serviceType, object service)
- {
- if (serviceType == null)
- {
- throw Error.ArgumentNull("serviceType");
- }
- _defaultServicesSingle[serviceType] = service;
- }
- //移除所有缓存
- private void ResetCache()
- {
- _cacheSingle = new ConcurrentDictionary<Type, object>();
- _cacheMulti = new ConcurrentDictionary<Type, object[]>();
- _lastKnownDependencyResolver = _configuration.DependencyResolver;
- }
- //重写方法 移除某个服务的缓存
- protected override void ResetCache(Type serviceType)
- {
- object single;
- _cacheSingle.TryRemove(serviceType, out single);
- object[] multiple;
- _cacheMulti.TryRemove(serviceType, out multiple);
- }
- }
3、HttpConfiguration
- public class HttpConfiguration : IDisposable
- {
- private readonly HttpRouteCollection _routes;
- private readonly ConcurrentDictionary<object, object> _properties = new ConcurrentDictionary<object, object>();
- private readonly MediaTypeFormatterCollection _formatters;
- private readonly Collection<DelegatingHandler> _messageHandlers = new Collection<DelegatingHandler>();
- private readonly HttpFilterCollection _filters = new HttpFilterCollection();
- //IDependencyResolver
- private IDependencyResolver _dependencyResolver = EmptyResolver.Instance;
- private Action<HttpConfiguration> _initializer = DefaultInitializer;
- private bool _initialized;
- private bool _disposed;
- public HttpConfiguration()
- : this(new HttpRouteCollection(String.Empty))
- {
- }
- public HttpConfiguration(HttpRouteCollection routes)
- {
- if (routes == null)
- {
- throw Error.ArgumentNull("routes");
- }
- _routes = routes;
- _formatters = DefaultFormatters(this);
- //使用DefaultServices
- Services = new DefaultServices(this);
- ParameterBindingRules = DefaultActionValueBinder.GetDefaultParameterBinders();
- }
- //内部设置
- public ServicesContainer Services { get; internal set; }
- }
4、ServicesExtensions
ServicesContainer扩展方法,方便调用,调用具体的某个服务类型的服务实例,空判断,抛异常。
- public static class ServicesExtensions
- {
- public static IEnumerable<ModelBinderProvider> GetModelBinderProviders(this ServicesContainer services)
- {
- return services.GetServices<ModelBinderProvider>();
- }
- public static ModelMetadataProvider GetModelMetadataProvider(this ServicesContainer services)
- {
- return services.GetServiceOrThrow<ModelMetadataProvider>();
- }
- public static IEnumerable<ModelValidatorProvider> GetModelValidatorProviders(this ServicesContainer services)
- {
- return services.GetServices<ModelValidatorProvider>();
- }
- internal static IModelValidatorCache GetModelValidatorCache(this ServicesContainer services)
- {
- return services.GetService<IModelValidatorCache>();
- }
- public static IContentNegotiator GetContentNegotiator(this ServicesContainer services)
- {
- return services.GetService<IContentNegotiator>();
- }
- public static IHttpControllerActivator GetHttpControllerActivator(this ServicesContainer services)
- {
- return services.GetServiceOrThrow<IHttpControllerActivator>();
- }
- public static IHttpActionSelector GetActionSelector(this ServicesContainer services)
- {
- return services.GetServiceOrThrow<IHttpActionSelector>();
- }
- public static IHttpActionInvoker GetActionInvoker(this ServicesContainer services)
- {
- return services.GetServiceOrThrow<IHttpActionInvoker>();
- }
- public static IActionValueBinder GetActionValueBinder(this ServicesContainer services)
- {
- return services.GetService<IActionValueBinder>();
- }
- public static IEnumerable<ValueProviderFactory> GetValueProviderFactories(this ServicesContainer services)
- {
- return services.GetServices<ValueProviderFactory>();
- }
- public static IBodyModelValidator GetBodyModelValidator(this ServicesContainer services)
- {
- return services.GetService<IBodyModelValidator>();
- }
- public static IHostBufferPolicySelector GetHostBufferPolicySelector(this ServicesContainer services)
- {
- return services.GetService<IHostBufferPolicySelector>();
- }
- public static IHttpControllerSelector GetHttpControllerSelector(this ServicesContainer services)
- {
- return services.GetServiceOrThrow<IHttpControllerSelector>();
- }
- public static IAssembliesResolver GetAssembliesResolver(this ServicesContainer services)
- {
- return services.GetServiceOrThrow<IAssembliesResolver>();
- }
- public static IHttpControllerTypeResolver GetHttpControllerTypeResolver(this ServicesContainer services)
- {
- return services.GetServiceOrThrow<IHttpControllerTypeResolver>();
- }
- public static IApiExplorer GetApiExplorer(this ServicesContainer services)
- {
- return services.GetServiceOrThrow<IApiExplorer>();
- }
- public static IDocumentationProvider GetDocumentationProvider(this ServicesContainer services)
- {
- return services.GetService<IDocumentationProvider>();
- }
- public static IExceptionHandler GetExceptionHandler(this ServicesContainer services)
- {
- return services.GetService<IExceptionHandler>();
- }
- public static IEnumerable<IExceptionLogger> GetExceptionLoggers(this ServicesContainer services)
- {
- return services.GetServices<IExceptionLogger>();
- }
- public static IEnumerable<IFilterProvider> GetFilterProviders(this ServicesContainer services)
- {
- return services.GetServices<IFilterProvider>();
- }
- public static ITraceManager GetTraceManager(this ServicesContainer services)
- {
- return services.GetService<ITraceManager>();
- }
- public static ITraceWriter GetTraceWriter(this ServicesContainer services)
- {
- return services.GetService<ITraceWriter>();
- }
- internal static IEnumerable<TService> GetServices<TService>(this ServicesContainer services)
- {
- if (services == null)
- {
- throw Error.ArgumentNull("services");
- }
- return services.GetServices(typeof(TService)).Cast<TService>();
- }
- // 通用的泛型方法,空判断,抛异常
- private static TService GetService<TService>(this ServicesContainer services)
- {
- if (services == null)
- {
- throw Error.ArgumentNull("services");
- }
- return (TService)services.GetService(typeof(TService));
- }
- private static T GetServiceOrThrow<T>(this ServicesContainer services)
- {
- T result = services.GetService<T>();
- if (result == null)
- {
- throw Error.InvalidOperation(SRResources.DependencyResolverNoService, typeof(T).FullName);
- }
- return result;
- }
- }
二、自定义组件扩展
扩展:
- public class ExtendedDefaultAssembliesResolver : DefaultAssembliesResolver
- {
- public override ICollection<Assembly> GetAssemblies()
- {
- PreLoadedAssembliesSettings settings = PreLoadedAssembliesSettings.GetSection();
- if (null != settings)
- {
- foreach (AssemblyElement element in settings.AssemblyNames)
- {
- AssemblyName assemblyName = AssemblyName.GetAssemblyName(element.AssemblyName);
- if (!AppDomain.CurrentDomain.GetAssemblies() .Any(assembly => AssemblyName.ReferenceMatchesDefinition(assembly.GetName(), assemblyName)))
- {
- AppDomain.CurrentDomain.Load(assemblyName);
- }
- }
- }
- return base.GetAssemblies();
- }
- }
注册:
- httpServer.Configuration.Services.Replace(typeof(IAssembliesResolver),new ExtendedDefaultAssembliesResolver());
ASP.NET Web API 框架研究 服务容器 ServicesContainer的更多相关文章
- ASP.NET Web API 框架研究 IoC容器 DependencyResolver
一.概念 1.IoC(Inversion of Control),控制反转 即将依赖对象的创建和维护交给一个外部容器来负责,而不是应用本身.如,在类型A中需要使用类型B的实例,而B的实例的创建不是由A ...
- ASP.NET Web API 框架研究 ASP.NET Web API 路由
ASP.NET Web API 核心框架是一个独立的.抽象的消息处理管道,ASP.NET Web API有自己独立的路由系统,是消息处理管道的组成部分,其与ASP.NET路由系统有类似的设计,都能找到 ...
- ASP.NET Web API 框架研究 Action方法介绍
在根据请求解析出匹配的Controller类型并创建实例后,要在该Controller类型中的众多Action方法中选择与请求匹配的那一个,并执行,然后返回响应. Action方法,其元数据,主要包括 ...
- ASP.NET Web API 框架研究 Controller实例的销毁
我们知道项目中创建的Controller,如ProductController都继承自ApiController抽象类,其又实现了接口IDisposable,所以,框架中自动调用Dispose方法来释 ...
- ASP.NET Web API 框架研究 Self Host模式下的消息处理管道
Self Host模式下的ASP.NET Web API与WCF非常相似,都可以寄宿在任意类型的托管应用程序中,宿主可以是Windows Form .WPF.控制台应用以及Windows Servic ...
- ASP.NET Web API 框架研究 核心的消息处理管道
ASP.NET Web API 的核心框架是一个由一组HttpMessageHandler有序组成的双工消息处理管道:寄宿监听到请求接受后,把消息传入该管道经过所有HttpMessageHandler ...
- ASP.NET Web API 框架研究 Web Host模式下的消息处理管道
寄宿的作用是开启一个进程为Web API提供一个运行环境以解决持续监听.请求监听和响应回复,即将接收到的请求转换成HttpRequestMessage对象传入管道,并将管道生成并经过处理后的HttpR ...
- ASP.NET Web API 框架研究 Web Host模式路由及将请求转出到消息处理管道
Web Host 模式下的路由本质上还是通过ASP.NET 路由系统来进行路由的,只是通过继承和组合的方式对ASP.NET路由系统的内部的类进行了一些封装,产生自己专用一套类结构,功能逻辑基本都是一样 ...
- ASP.NET Web API 框架研究 ASP.NET 路由
ASP.NET Web API 如果采用Web Host方式来寄宿,在请求进入Web API 消息处理管道之前,就会用ASP.NET 自身的路由系统根据注册的路由表,解析出当前请求的HttpContr ...
随机推荐
- Tech 2 doesn’t system for H2 above 2007
I purchased my Tech2 from obd2tool.com and it operates excellent. Can not definitely compare softwar ...
- shell脚本${}、##和%%使用范例
file=/dir1/dir2/dir3/my.file.txt 可以用${ }分别替换得到不同的值: ${file#*/}:删掉第一个 / 及其左边的字符串:dir1/dir2/dir3/my.fi ...
- FPKM与RPKM
FPKM与RPKM (2015-01-09 23:55:17) 转载▼ 标签: 转载 原文地址:FPKM与RPKM作者:Fiona_72965 定义: FPKM:Fragment Per Kil ...
- Luogu 2467[SDOI2010]地精部落 - DP
Solution 这题真秒啊,我眼瞎没有看到这是个排列 很显然, 有一条性质: 第一个是山峰 和 第一个是山谷的情况是一一对应的, 只需要把每个数 $x$ 变成 $n-x+1$ 然后窝萌定义数组 $ ...
- 20172306《Java程序设计》第四周学习总结
20172306 <Java程序设计>第四周学习总结 教材学习内容总结 第四章: 1. 类和对象的回顾:除了看书,我还上网找了一下两者的一些区别. 2. 编写类时,了解到初始化.形式参数. ...
- Android资源相关语法
2018-08-29 getResources().getString(Rid)获取配置中的字符串
- tomcat与jmeter
jmeter无法提取出Tomcat之外的其他服务器的指标. 为了克服这一现状,研发了一个服务器代理,jmeter通过这个代理来获取性能数据. 代理使用的是sigar开源库,他是一个java通过部分和一 ...
- GOIP connects with Elastix through “config by line”
GOIP connects with Elastix through “config by line” By grace Liu on May 17, 2013 in Elastix, Gateway ...
- 失踪的7(P1590&NOIP水题测试(2017082301))
题目链接:失踪的7 水题,不解释. #include<bits/stdc++.h> using namespace std; int main(){ int t; scanf(" ...
- UVALive-7041(回文树
题意:给你两个字符串,问你有多少对公共回文串. 思路:先对a字符串建回文树.然后再把b字符串加进去就好了. #include<cstdio> #include<cmath> # ...