ASP.NET Web API操作方法参数的dependency injection
我正在使用C#中的ASP.NET Web API项目来获取移动应用程序的JSON接口。 我的想法是为所有请求创建接口,然后仅在Web API代码中使用这些接口。
我最终得到了这样的东西:
public interface IApiObject {} public interface IApiResponse : IApiObject where T : IApiObject {} public interface IApiRegistrationRequest : IApiObject {}
我的控制器看起来像这样:
public class MyApiController : ApiController { public IApiResponse Register(IApiRegistrationRequest request) { // do some stuff } }
我的Web API项目还包含这些接口的实现。
我假设Web API项目使用像MVC项目那样的模型绑定,因此我创建了一个inheritance感知的ModelBinderProvider,用于为所有IApiObjects提供一个绑定器,并使用Unity容器为其实现的接口解析自定义模型绑定器。
但是,经过一些调查,我发现了Web API 如何进行参数绑定,并发现Web API使用格式化程序而不是复杂类型的模型绑定程序。 链接的博客文章建议在我的操作参数上使用ModelBinderAttribute,但该属性仅接受类型作为参数。 但是,我的自定义模型绑定器不包含空构造函数(它需要一个统一容器),所以我需要传递它的一个实例。
我能想到的另一种方法是使用dependency injection格式化程序。 不幸的是,我不熟悉它们,因为我以前从未使用它们。
哪种方式正确? 我该怎么办?
这就是我现在提出的,它的工作原理。
我决定创建一个自定义格式化程序,它执行统一调用,并使用已解析的类型将所有进一步的操作转发给另一个格式化程序。 它看起来像很多代码,但这只是因为所有方法都需要被覆盖,因此可以始终解析类型。
public class UnityFormatter : MediaTypeFormatter { private MediaTypeFormatter formatter; private IUnityContainer container; public UnityFormatter(MediaTypeFormatter formatter, IUnityContainer container) { this.formatter = formatter; this.container = container; foreach (var supportedMediaType in this.formatter.SupportedMediaTypes) { this.SupportedMediaTypes.Add(supportedMediaType); } foreach (var supportedEncoding in this.formatter.SupportedEncodings) { this.SupportedEncodings.Add(supportedEncoding); } foreach (var mediaTypeMapping in this.MediaTypeMappings) { this.MediaTypeMappings.Add(mediaTypeMapping); } this.RequiredMemberSelector = this.formatter.RequiredMemberSelector; } private Type ResolveType(Type type) { return this.container.Registrations.Where(n => n.RegisteredType == type).Select(n => n.MappedToType).FirstOrDefault() ?? type; } public override bool CanReadType(Type type) { return this.formatter.CanReadType(this.ResolveType(type)); } public override bool CanWriteType(Type type) { return this.formatter.CanWriteType(this.ResolveType(type)); } public override MediaTypeFormatter GetPerRequestFormatterInstance(Type type, HttpRequestMessage request, MediaTypeHeaderValue mediaType) { return this.formatter.GetPerRequestFormatterInstance(this.ResolveType(type), request, mediaType); } public override Task
最后,在应用程序配置(Global.asax Application_Start)中注册我们的自定义格式化程序。 我选择用我的自定义实例替换所有当前格式化程序,因此我得到所有数据类型的reflection。
// set up unity container, register all types UnityContainer container = new UnityContainer(); container.RegisterType(); // save existing formatters and remove them from the config List formatters = new List (GlobalConfiguration.Configuration.Formatters); GlobalConfiguration.Configuration.Formatters.Clear(); // create an instance of our custom formatter for each existing formatter foreach (MediaTypeFormatter formatter in formatters) { GlobalConfiguration.Configuration.Formatters.Add(new UnityFormatter(formatter, container)); }
我建议你看一下服务栈http://www.servicestack.net/
它的设计与asp.net-WebApi完全相同,但它有像IOC一样的好东西。
http://pluralsight.com/training/Courses/TableOfContents/service-stack上有一系列关于服务堆栈的精彩系列