Web API 依赖注入与扩展

简介:

依赖注入

与 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 框架将会在运行时向其请求一系列的接口实现:

  1. 应用启动时, Web API 框架会依次请求下列接口:
    1. System.Web.Http.Dispatcher.IHttpControllerFactory
    2. System.Web.Http.Common.ILogger
    3. System.Web.Http.Dispatcher.IHttpControllerActivator
    4. System.Web.Http.Controllers.IHttpActionSelector
    5. System.Web.Http.Controllers.IHttpActionInvoker
  2. 在第一次访问某个 Controller 之前, 还会请求下面的接口 (如果重复访问相同的 Controller , 则不会再次调用):
    1. System.Web.Http.Filters.IFilterProvider
  3. 每次处理 HTTP 请求时, Web API 请求下列接口:
    1. System.Web.Http.Controllers.IActionValueBinder
    2. System.Web.Http.ValueProviders.ValueProviderFactory (仅 Action 需要参数时才需要)
    3. System.Web.Http.ModelBinding.ModelBinderProvider (仅 Action 需要参数时才需要)
    4. System.Web.Http.Metadata.ModelMetadataProvider (仅 Action 需要参数时才需要)
    5. System.Web.Http.Validation.ModelValidatorProvider (仅 Action 需要参数时才需要)
    6. 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 , 选择规则如下:

  1. 如果路由定义了 {action} , 则通过当前的 HttpControllerContext 中的 action 的值寻找合适的方法;
  2. 否则, 根据当前的 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 格式的读取与写入。

张志敏所有文章遵循创作共用版权协议,要求署名、非商业 、保持一致。在满足创作共用版权协议的基础上可以转载,但请以超链接形式注明出处。

本博客已经迁移到 GitHub , 围观地址: http://beginor.github.io/

本文转自张志敏博客园博客,原文链接:http://www.cnblogs.com/beginor/archive/2012/03/22/2411496.html ,如需转载请自行联系原作者
相关文章
|
1月前
|
JSON API 数据库
解释如何在 Python 中实现 Web 服务(RESTful API)。
解释如何在 Python 中实现 Web 服务(RESTful API)。
26 0
|
1月前
|
缓存 关系型数据库 API
后端开发:构建高效、可扩展的Web应用程序的关键
后端开发:构建高效、可扩展的Web应用程序的关键
22 0
|
29天前
|
安全 API 开发者
构建高效可扩展的RESTful API服务
在数字化转型的浪潮中,构建一个高效、可扩展且易于维护的后端API服务是企业竞争力的关键。本文将深入探讨如何利用现代后端技术栈实现RESTful API服务的优化,包括代码结构设计、性能调优、安全性强化以及微服务架构的应用。我们将通过实践案例分析,揭示后端开发的最佳实践,帮助开发者提升系统的响应速度和处理能力,同时确保服务的高可用性和安全。
30 3
|
1月前
|
缓存 前端开发 API
构建高效可扩展的RESTful API:后端开发的最佳实践
【2月更文挑战第30天】 在现代Web应用和服务端架构中,RESTful API已成为连接前端与后端、实现服务间通信的重要接口。本文将探讨构建一个高效且可扩展的RESTful API的关键步骤和最佳实践,包括设计原则、性能优化、安全性考虑以及错误处理机制。通过这些实践,开发者可以确保API的健壮性、易用性和未来的可维护性。
|
1月前
|
XML JSON API
通过Flask框架创建灵活的、可扩展的Web Restful API服务
通过Flask框架创建灵活的、可扩展的Web Restful API服务
|
1月前
|
缓存 监控 API
Python Web框架FastAPI——一个比Flask和Tornada更高性能的API框架
Python Web框架FastAPI——一个比Flask和Tornada更高性能的API框架
58 0
|
1月前
|
JSON API 数据格式
构建高效Python Web应用:Flask框架与RESTful API设计实践
【2月更文挑战第17天】在现代Web开发中,轻量级框架与RESTful API设计成为了提升应用性能和可维护性的关键。本文将深入探讨如何使用Python的Flask框架来构建高效的Web服务,并通过具体实例分析RESTful API的设计原则及其实现过程。我们将从基本的应用架构出发,逐步介绍如何利用Flask的灵活性进行模块化开发,并结合请求处理、数据验证以及安全性考虑,打造出一个既符合标准又易于扩展的Web应用。
653 4
|
1月前
|
安全 应用服务中间件 nginx
|
2月前
|
前端开发 JavaScript API
前端秘法番外篇----学完Web API,前端才能算真正的入门
前端秘法番外篇----学完Web API,前端才能算真正的入门
|
2月前
|
API 网络架构
解释 RESTful API,以及如何使用它构建 web 应用程序。
解释 RESTful API,以及如何使用它构建 web 应用程序。
88 0