ASP.NET Web API 框架研究 IoC容器 DependencyResolver
一、概念
1、IoC(Inversion of Control),控制反转
即将依赖对象的创建和维护交给一个外部容器来负责,而不是应用本身。如,在类型A中需要使用类型B的实例,而B的实例的创建不是由A负责,而是由外部容器来创建。
2、DI(Dependency Injection),依赖注入
即外部容器在运行时候动态的将依赖类型的实例对象注入到应用中。其与IoC联系一起,因为IoC才需要DI。当然,实例对象也可以直接调用IoC容器的方法(如GetService)获得。DI分三种形式:
- 构造函数注入(Constructor Injection):构造函数的参数定义为一个抽象依赖类型,IoC容器在调用A的构造函数创建对象之前会解析注册的依赖关系并创建对应的依赖类型的实例。
public A(IB b)
{
_b = b;
}
- 属性注入(Property Injection):在对象A被IoC容器创建时候,Ioc容器自动通过Set对该属性赋值为该类型(B)注册的实例对象;用Unity时候,属性要标注[Dependency]特性
[Dependency]
public IB B { get; set; }
- 方法注入(Method Injection):在对象A被IoC容器创建时候,自动调用方法;用Unity时候,方法要标注[InjectionMethod]特性
[InjectionMethod]
public void SetInjection(IB b)
{
_b = b;
}
3、IoC容器
负责根据依赖类型注册的类型创建实例对象,解决对象之间的抽象依赖关系,用来返回服务接口类型服务实例。
二、DependencyReslover
是ASP.NET Web API内部使用的一个IoC容器;它继承IDependencyReslover接口,其又继承IDependencyScope ,默认实现是EmptyResolver ,相当于默认是没有IoC容器功能,不能返回任何类型的实例。涉及的类,如下图:

源代码如下:
public interface IDependencyScope : IDisposable
{
object GetService(Type serviceType);
IEnumerable<object> GetServices(Type serviceType);
}
public interface IDependencyResolver : IDependencyScope
{
IDependencyScope BeginScope();
}
internal class EmptyResolver : IDependencyResolver
{
private static readonly IDependencyResolver _instance = new EmptyResolver(); private EmptyResolver()
{
} public static IDependencyResolver Instance
{
get { return _instance; }
}
public IDependencyScope BeginScope()
{
return this;
} public void Dispose()
{
} public object GetService(Type serviceType)
{
return null;
} public IEnumerable<object> GetServices(Type serviceType)
{
return Enumerable.Empty<object>();
}
}
另外,EmptyResolver 的指定,不是在ServicesContainer,而是直接在HttpConfiguration里指定,如下代码段

三、自定义扩展IDependencyReslover
EmptyResolver没有IoC功能,想要使用IoC的功能,必须自定义扩展IDependencyReslover,该接口是ASP.NET Web API和IoC工具的桥梁,工具如Unity,Ninject
1、使用Unity
public class UnityResolver : IDependencyResolver
{
protected IUnityContainer container; public UnityResolver(IUnityContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
this.container = container;
} public object GetService(Type serviceType)
{
try
{
if(container.IsRegistered(serviceType))
{
return container.Resolve(serviceType);
}
else
{
return null;
}
}
catch (ResolutionFailedException)
{
return null;
}
} public IEnumerable<object> GetServices(Type serviceType)
{
try
{
if(container.IsRegistered(serviceType))
{
return container.ResolveAll(serviceType);
}
else
{
return new List<object>();
}
}
catch (ResolutionFailedException)
{
return new List<object>();
}
} public IDependencyScope BeginScope()
{
var child = container.CreateChildContainer();
return new UnityResolver(child);
} public void Dispose()
{
container.Dispose();
}
}
注册:
public static void Register(HttpConfiguration config)
{
var container = new UnityContainer();
//如果GetService没有IsRegistered判断,可以不用注册,直接可以根据Type获取实例
container.RegisterType<ProductController>();
container.RegisterType<IProductRepository, ProductRepository>();
config.DependencyResolver = new UnityResolver(container); config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
2、使用Ninject
public class NinjectDependencyResolver : IDependencyResolver
{
private List<IDisposable> disposableServices = new List<IDisposable>();
public IKernel Kernel { get; private set; } public NinjectDependencyResolver(NinjectDependencyResolver parent)
{
this.Kernel = parent.Kernel;
} public NinjectDependencyResolver()
{
this.Kernel = new StandardKernel();
} public void Register<TFrom, TTo>() where TTo : TFrom
{
this.Kernel.Bind<TFrom>().To<TTo>();
} public IDependencyScope BeginScope()
{
return new NinjectDependencyResolver(this);
} public object GetService(Type serviceType)
{
return this.Kernel.TryGet(serviceType);
} public IEnumerable<object> GetServices(Type serviceType)
{
foreach (var service in this.Kernel.GetAll(serviceType))
{
this.AddDisposableService(service);
yield return service;
}
} public void Dispose()
{
foreach (IDisposable disposable in disposableServices)
{
disposable.Dispose();
}
} private void AddDisposableService(object servie)
{
IDisposable disposable = servie as IDisposable;
if (null != disposable && !disposableServices.Contains(disposable))
{
disposableServices.Add(disposable);
}
}
}
注册:
NinjectDependencyResolver dependencyResolver = new NinjectDependencyResolver();
dependencyResolver.Register<IContactRepository, DefaultContactRepository>();
GlobalConfiguration.Configuration.DependencyResolver = dependencyResolver;
ASP.NET Web API 框架研究 IoC容器 DependencyResolver的更多相关文章
- ASP.NET Web API 框架研究 服务容器 ServicesContainer
ServicesContainer是一个服务的容器,可以理解为—个轻量级的IoC容器,其维护着一个服务接口类型与服务实例之间的映射关系,可以根据服务接口类型获取对应的服务实例.构成ASP.NET We ...
- 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 框架研究 核心的消息处理管道
ASP.NET Web API 的核心框架是一个由一组HttpMessageHandler有序组成的双工消息处理管道:寄宿监听到请求接受后,把消息传入该管道经过所有HttpMessageHandler ...
- ASP.NET Web API 框架研究 Self Host模式下的消息处理管道
Self Host模式下的ASP.NET Web API与WCF非常相似,都可以寄宿在任意类型的托管应用程序中,宿主可以是Windows Form .WPF.控制台应用以及Windows Servic ...
- 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 ...
随机推荐
- 关于nodejs 假设httpserver,会发现一次网页打开,服务端会响应两次的问题;
转自:http://cnodejs.org/topic/518772806d38277306804020 每个页面默认都会再发一个de style="line-height: 21px; p ...
- 关于LCA的倍增解法的笔记
emmmmm近日刚刚学习了LCA的倍增做法,写一篇BLOG来加强一下印象w 首先 何为LCA? LCA“光辉”是印度斯坦航空公司(HAL)为满足印度空军需要研制的单座单发轻型全天候超音速战斗攻击机,主 ...
- dbc file
DBC文件是用来描述CAN网络通信信号的一种格式文件.它可以用来监测与分析CAN网络上的报文数据,也可以用来模拟某个CAN节点.(DBC file is a format file used to d ...
- 对团队项目的NABCD的分析
需求(N):我们的软件是面向广大想记录自己所爱动植物成长点滴的人.目前没有很好地软件,只有手机或者电脑上的笔记本和备忘录. 做法(A):我们的软件可以交流可以节约积累知识的时间,将记录从记事本中摘出来 ...
- ECLIPSE使用HG插件去上载 GOOGLE.CODE下的代码
ECLIPSE使用HG插件去上载 GOOGLE.CODE下的代码 www.MyException.Cn 发布于:2012-09-10 22:20:12 浏览:112次 0 ECLIPSE使 ...
- mui-手动触发下拉刷新
mui-手动触发下拉刷新 下拉刷新结束 mui官方文档中下拉刷新结束方法,不生效, 文档地址 1 mui('#refreshContainer').pullRefresh().endPulldow ...
- Mac下Maven安装与配置
Mac下Maven安装与配置 下载maven http://maven.apache.org/download.cgi main->download菜单下的Files 下载后解压在Documen ...
- [转]order by 与索引
ORDER BY 通常会有两种实现方法,一个是利用有序索引自动实现,也就是说利用有序索引的有序性就不再另做排序操作了.另一个是把结果选好之后再排序. 用有序索引这种,当然是最快的,不过有一些限制条件, ...
- oracle unix时间戳与date转换
linux 时间戳 转date: 创建自定义函数: create or replace function unix_to_oracle(in_number number) return date ...
- 7个鲜为人知却超实用的PHP函数--转(柒捌玖零)
PHP有许多内置函数,其中大多数函数都被程序员广泛使用.但也有一些函数隐藏在角落,本文将向大家介绍7个鲜为人知,但用处非常大的函数. 没用过的程序员不妨过来看看. 1.highlight_string ...