MVC核心功能组件和简介
依赖注入
与 MVC 类似, Web API 提供了System.Web.Http.Services.IDependencyResolver 接口来实现依赖注入, 我们可以很容易的用 Unity 来实现这个接口:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
public class UnityDependencyResolver : IDependencyResolver {
private readonly IUnityContainer _container;
public UnityDependencyResolver(IUnityContainer container) {
this ._container = container;
}
public object GetService(Type serviceType) {
return this ._container.IsRegistered(serviceType) ? this ._container.Resolve(serviceType) : null ;
}
public IEnumerable<Object> GetServices(Type serviceType) {
return this ._container.Registrations
.Where(reg => type.IsAssignableFrom(reg.RegisteredType))
.Select(reg => string .IsNullOrEmpty(reg.Name) ? this ._container.Resolve(type) : this ._container.Resolve(type, reg.Name));
}
}
|
使用 UnityDependencyResolver 的方法也很简单, 只要在 Global.asax.cs 里添加下面一行代码即可:
1
|
GlobalConfiguration.Configuration.ServiceResolver.SetResolver( new UnityDependencyResolver(container));
|
将 UnityDependencyResolver 配置好之后, Web API 框架将会在运行时向其请求一系列的接口实现:
- 应用启动时, Web API 框架会依次请求下列接口:
- System.Web.Http.Dispatcher.IHttpControllerFactory
- System.Web.Http.Common.ILogger
- System.Web.Http.Dispatcher.IHttpControllerActivator
- System.Web.Http.Controllers.IHttpActionSelector
- System.Web.Http.Controllers.IHttpActionInvoker
- 在第一次访问某个 Controller 之前, 还会请求下面的接口 (如果重复访问相同的 Controller , 则不会再次调用):
- System.Web.Http.Filters.IFilterProvider
- 每次处理 HTTP 请求时, Web API 请求下列接口:
- System.Web.Http.Controllers.IActionValueBinder
- System.Web.Http.ValueProviders.ValueProviderFactory (仅 Action 需要参数时才需要)
- System.Web.Http.ModelBinding.ModelBinderProvider (仅 Action 需要参数时才需要)
- System.Web.Http.Metadata.ModelMetadataProvider (仅 Action 需要参数时才需要)
- System.Web.Http.Validation.ModelValidatorProvider (仅 Action 需要参数时才需要)
- System.Net.Http.Formatting.IFormatterSelector
这些接口都是 Web API 公开的扩展点, 可以根据需要来对这些接口进行实现, 并通过 Unity 进行配置, 让其注入到 Web API 运行时中。 接下来将逐个讨论这些扩展点。
扩展
IHttpControllerFactory
IHttpControllerFactory 接口有两个方法, 负责创建和销毁 HttpController 实例:
- CreateController(HttpControllerContext, Type) : IHttpController
- ReleaseController(IHttpController) : void
这个接口的默认实现是 DefaultHttpControllerFactory , 根据当前请求的上下文通过创建 HttpControllerDescriptor , 然后通过 HttpControllerDescriptor 的 ControllerActivator 创建对应的 IHttpController 实例。
ILogger
只是一个日志接口, 有下面的几个方法:
- Log(string, TraceLevel, Func) : void
- LogException(string, TraceLevel, Exception) : void
默认的实现是 DiagnosticLogger , 通过 ILSpy 观察, 貌似什么都没有做。
IHttpControllerActivator
负责创建具体的 Controller 实例, 只有一个方法:
- Create(HttpControllerContext, Type) : IHttpController
默认的实现是 DefaultHttpControllerActivator , 先向 DependencyResolver 请求对应 Controller 类型的实例, 如果返回为空, 则通过动态编译包装 Controller 类型构造函数的 lambda 表达式进行创建实例, 相关的代码如下:
1
2
3
4
|
Func<IHttpController> func = TypeActivator.Create<IHttpController>(controllerType);
Tuple<HttpControllerDescriptor, Func<IHttpController>> value = Tuple.Create<HttpControllerDescriptor, Func<IHttpController>>(controllerContext.ControllerDescriptor, func);
Interlocked.CompareExchange<Tuple<HttpControllerDescriptor, Func<IHttpController>>>( ref this ._fastCache, value, null );
result = func();
|
IHttpActionSelector
负责选择合适的动作, 默认的实现是 ApiControllerSelector , 选择规则如下:
- 如果路由定义了 {action} , 则通过当前的 HttpControllerContext 中的 action 的值寻找合适的方法;
- 否则, 根据当前的 HTTP 请求方法 (POST, GET, PUT, DELETE) 寻找合适的方法。
IHttpActionInvoker
负责调用 HttpActionSelector 选择到的方法, 该接口有一个方法:
- InvokeActionAsync(HttpActionContext, CancellationToken) : Task<HttpResponseMessage>
默认的实现是 ApiControllerActionInvoker , 通过反射找出动作方法的参数信息, 然后再通过动态创建 lambda 表达式对方法进行调用, 取得返回结果, 部分代码如下:
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
|
ParameterExpression parameterExpression = Expression.Parameter( typeof ( object ), "instance" );
ParameterExpression parameterExpression2 = Expression.Parameter( typeof ( object []), "parameters" );
List<Expression> list = new List<Expression>();
ParameterInfo[] parameters = methodInfo.GetParameters();
for ( int i = 0; i < parameters.Length; i++)
{
ParameterInfo parameterInfo = parameters[i];
BinaryExpression expression = Expression.ArrayIndex(parameterExpression2, Expression.Constant(i));
UnaryExpression item = Expression.Convert(expression, parameterInfo.ParameterType);
list.Add(item);
}
UnaryExpression instance2 = (!methodInfo.IsStatic) ? Expression.Convert(parameterExpression, methodInfo.ReflectedType) : null ;
MethodCallExpression methodCallExpression = Expression.Call(instance2, methodInfo, list);
if (methodCallExpression.Type == typeof ( void ))
{
Expression<Action< object , object []>> expression2 = Expression.Lambda<Action< object , object []>>(methodCallExpression, new ParameterExpression[]
{
parameterExpression,
parameterExpression2
});
Action< object , object []> voidExecutor = expression2.Compile();
return delegate ( object instance, object [] methodParameters)
{
voidExecutor(instance, methodParameters);
return null ;
}
;
}
UnaryExpression body = Expression.Convert(methodCallExpression, typeof ( object ));
Expression<Func< object , object [], object >> expression3 = Expression.Lambda<Func< object , object [], object >>(body, new ParameterExpression[]
{
parameterExpression,
parameterExpression2
});
return expression3.Compile();
|
取得返回结果之后, 再调用 ApiResponseConverter 的 GetResponseConverter 方法找到合适的 Converter , 最后返回 Task<HttpResponseMessage>
IFilterProvider
负责提供过滤的标记, Web API 框架内置了下面的几个 FilterProvider :
- EnumerableEvaluatorFilterProvider 负责提供对 IENumerable 的每个元素的转换的标记, 简单的说, 就是负责提供将 Action 方法返回的 IEnumerable 的结果进行自定义转换的标记;
- QueryCompositionFilterProvider 负责对 Action 方法返回的 IQueryable 的结果进行符合 OData 约定的 URL 参数进行再次过滤的标记 QueryCompositionFilterAttribute , 目前只支持 $filter 、 $orderby 、 $skip 以及 $top ;
- ActionDescriptorFilterProvider
- ConfigurationFilterProvider
注意, 这里说的是 FilterProvider, 不是 Filter , 也不是 FilterAttribute 。
IActionValueBinder
负责绑定 Action 方法的参数, 默认的实现是 DefaultActionValuebinder , 通过调用 ValueProviderFactory 、 ModelBinderProvider 进行参数绑定, 支持多种形式的参数绑定, 绑定策略比较复杂, 总的来说是简单的参数从 URL 中绑定, 复杂参数从 HTTP 请求内容中获取。
ValueProviderFactory
定义了 Action 参数从哪里获取, 有以下几个实现, 分别支持从 URI 、 QueryString、 Post 内容中提取参数值:
- CompositeValueProviderFactory
- KeyValueModelProviderFactory
- RouteDataValueProviderFactory
- QueryStringValueProviderFactory
ModelBinderProvider
定义了如何将获取到的 HTTP 请求的的参数之绑定到指定的参数。 System.Web.Http.ModelBinding.Binders 命名空间内提供了多种 BinderProvider , 应该可以处理大多数常见的类型。
ModelMetadataProvider
负责提供模型元数据描述信息。
ModelValidatorProvider
负责根据元素据信息对模型进行验证。
IFormatterSelector
负责选择合适的格式, 包括客户端请求的格式以及服务端返回的格式, 默认实现是 FormatterSelector , 能够提下面的 MediaFormater :
- BufferedmediaTypeFormatter 提供对二进制格式的读取与写入;
- FormUrlEncodedMediaTypeFormatter 提供对表单 URL 编码格式的读取与写入;
- JsonMediaTypeFormatter 提供对 Json 格式的读取与写入;
- XmlMediaFormatter 提供对 XML 格式的读取与写入。
转载自:http://www.cnblogs.com/beginor/archive/2012/03/22/2411496.html
转载于:https://www.cnblogs.com/kericai/archive/2013/01/12/2857811.html
MVC核心功能组件和简介相关推荐
- 002 第一季SpringBoot2核心技术-核心功能:配置文件、Web开发(原生组件)、数据访问、单元测试、指标监控、原理解析:@Value、命令行参数、手动获取bean、自定义starter
三.核心技术之- ->核心功能 1. 配置文件 1.1 文件类型 1.1.1 properties 同以前的properties用法 优先级高于yml的方式. 1.1.2 yaml 1) 简介 ...
- Springboot总结,核心功能,优缺点
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 作者:lizmit https://blog.csdn.net/q ...
- 一文带你看懂Springboot核心功能及优缺点
点击上方[视学算法]→右上角[...]→[设为星标⭐] SpringBoot核心功能 1.独立运行Spring项目 Spring boot 可以以jar包形式独立运行,运行一个Spring Boot项 ...
- Shiro 核心功能案例讲解 基于SpringBoot 有源码
Shiro 核心功能案例讲解 基于SpringBoot 有源码 从实战中学习Shiro的用法.本章使用SpringBoot快速搭建项目.整合SiteMesh框架布局页面.整合Shiro框架实现用身份认 ...
- 问题小结(二)——maven的核心功能、面向对象编程和面向接口编程的区别、抽象类和接口的区别等
文章目录 1. Java创建对象有哪四种方式? 2. 什么是maven?maven的核心功能有哪些? 3. 什么是MVC?说说分层的好处. 4. Spring的两大核心技术是什么? 5. 什么是IOC ...
- ASP.NET Core MVC – Tag Helper 组件
ASP.NET Core Tag Helpers系列目录,这是第五篇,共五篇: ASP.NET Core MVC – Tag Helpers 介绍 ASP.NET Core MVC – Caching ...
- 史上最强Dubbo面试28题答案详解:核心功能+服务治理+架构设计等
1.Dubbo是什么? Dubbo 是一个分布式.高性能.透明化的 RPC 服务框架,提供服务自动注册.自动发现等高效服务治理方案, 可以和 Spring 框架无缝集成. RPC 指的是远程调用协议, ...
- Java核心类库篇1——简介
Java核心类库篇1--简介 1.核心类库 包名 主要功能 java.applet 提供了创建applet需要的所有类 java.awt.* 提供了创建用户界面以及绘制和管理图形.图像的类 java. ...
- java mybatis的作用,【java框架】MyBatis-Plus(1)--MyBatis-Plus快速上手开发及核心功能体验-博客...
1.MyBatis-Plus入门开发及配置 1.1.MyBatis-Plus简介 MyBatis-Plus(简称 MP)是一个 MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变, ...
最新文章
- R语言构建xgboost模型:模型的特性重要度计算及可视化、模型对应的结构树(文本文件)
- .vue文件中style标签的几个标识符
- 设计模式-工厂模式学习(初级)
- Spring5源码 - 05 invokeBeanFactoryPostProcessors 源码解读_2
- Spring4新特性——核心容器的其他改进
- CCF——图像旋转201503-1
- python中的下标索引
- abrels.inc.php_setlist.js
- 基于Matlab的跨孔层析成像的最短路径法弯曲射线追踪(二)
- RFM模型+SOM聚类︱离群值筛选问题
- linux fdisk运用
- BackTrack4安装中文语言包
- 华为android解锁,华为bootloader怎么解锁 华为手机bootloader解锁教程
- 高德poi类别23个大类	261个中类	4705个小类
- Linux 下文件和目录的特点
- 计算机高程知识点,测量学复习基本知识点(全).doc
- PostgreSQL 中的系统字段:tableoid、xmin、xmax、cmin、cmax、ctid
- 如何理解混淆矩阵,以及预测少数类的评估指标?
- java 消息摘要_java – 使用BouncyCastle签名消息摘要
- Ubuntu18.04下更改apt源为阿里云源
热门文章
- python3urllib中的quote与encode的区别_Python的urllib.quote()和urllib.unquote()的等效Javascript函数...
- python的类与模块_Python类与模块属性
- 2021.12.15
- hihoCoder #1384 : Genius ACM [枚举+倍增]
- java classloader_Java Classloader原理分析
- Centos7 网络配置
- Phyton自定义包导入。
- 在Servlet使用getServletContext()获取ServletContext对象出现java.lang.NullPointerException(空指针)异常的解决办法...
- Httpster –世界各地最潮的网页设计案例聚合网站
- CSS Grid layout布局