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 ...
随机推荐
- Firebird存储过程--更加人性化的设计
Firebird存储过程--更加人性化的设计 begin For select house_id,goods_id ,qty from table1 where id=:VAR_ID into :v ...
- [SoapUI] 通过JSONAssert比较两个环境的JSON Response,定制化错误信息到Excel
package ScriptLibrary; import org.json.JSONArray; import org.json.JSONException; import org.json.JSO ...
- nginx域名转发 负载均衡 反向代理
公司有三台机器在机房,因为IP不够用,肯定要分出来,所以要建立单IP 多域名的反向代理, 就是当请求www.abc.com 跳转到本机, 请求www.bbc.com 跳转到192.168.0.35 机 ...
- DbUtils类的添加,修改,删除
package cn.jy.demo; import java.sql.Connection;import java.sql.SQLException; import org.apache.commo ...
- JS高级-Date- Error-***Function:
1. Date: API: 1. 8个单位: FullYear Month Date Day Hours Minutes Seconds Milliseconds 2. 每 ...
- kbmMW均衡负载与容灾(3)(转载红鱼儿)
在kbmMW均衡负载与容灾(1)中,介绍了利用ClientTransport的OnReconnect事件,对联接的应用服务器的地址进行更换,做容灾处理.实际上,作者还给我们提供了另外一种机制,直接在C ...
- Python10/17-re模块/hashlib模块/logging模块
import logging # 1.日志的级别# logging.debug("这是一个调试信息") # 10# logging.info("常规信息") # ...
- RF 和 GBDT联系和区别
1.RF 原理 用随机的方式建立一个森林,森林里面有很多的决策树,随机森林的每一棵决策树之间是没有关联的.在得到森林之后,当有一个新的输入样本进入的时候,就让森林中的每一棵决策树分别进行一下判断,看看 ...
- Codeforces 1103 简要题解(持续更新)
文章目录 A题 B题 C题 D题 传送门 又一场原地爆炸的比赛. A题 传送门 简单思维题 题意:给一个4∗44*44∗4的格子图和一个01串,你要根据01串放1∗21*21∗2的木块,如果是0就竖放 ...
- R入门(二)-对象以及它们的模式和属性
对象以及它们的模式和属性 R操作的实体在技术上说是对象.R的对象类型包括数值型,复数型,逻辑型,字符型和原味型. “原子”型对象:对象的元素都是一样的类型或模式,如逻辑向量和字符串向量. 列表对象:列 ...