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 ...
随机推荐
- iOS.GetCurrentTimestamp
Cocoa 中测量时间的方法 1. The Methods to Get Current Timestamp iOS中获取时间戳的方法: A. CACurrentMediaTime() B. gett ...
- GRADLE下运行main函数/执行测试用例
group 'gongsibao.ged' version '1.0-SNAPSHOT' apply plugin: 'java' apply plugin: 'idea' sourceCompati ...
- IPV6修复工具
https://www.cnblogs.com/ysugyl/p/9000940.html
- Apache Prefork、Worker和Event三种MPM分析
三种MPM介绍 Apache 2.X 支持插入式并行处理模块,称为多路处理模块(MPM).在编译apache时必须选择也只能选择一个MPM,对类UNIX系统,有几个不同的MPM可供选择,它们会影响到 ...
- delphi 中如何访问另一个类中到私有方法?(转载)
原始连接 http://rvelthuis.blogspot.tw/2018/01/accessing-private-methods-of-another.html Accessing privat ...
- De Bruijn序列
最近文章中经常出现及De Bruijin 这个关键字,网上搜索了一下,记录下来. De Bruijn序列 (德布鲁因序列) 问题:能否构造一个长度为2的n次方的二进制环状串,使得二进制环状串中总共2的 ...
- windows下mongodb安装与使用图文教程(整理)
一.首先安装mongodb 1.下载地址:http://www.mongodb.org/downloads 2.解压缩到自己想要安装的目录,比如d:\mongodb 3.创建文件夹d:\mongodb ...
- mysql 切换数据库方案
业务场景 在SAAS模式下,不同的租户需要切换数据库,我们可以使用动态数据源,动态数据源有个问题,就是需要对每一个数据库创建一个连接池,在初始化的时候初始化这些连接池, 如果多台应用服务器的情况,每一 ...
- shell知识积累
Ubuntu下常用的快捷键:https://blog.csdn.net/u010771356/article/details/53543041 变量名和等号之间不能有空格,变量名中间不能有空格,可以使 ...
- boost-使用说明
1. boost库中大部分组件不需要编译,直接包含对应头文件即可使用,如#include "boost/array.hpp",因为组件的声明和实现都包含在头文件hpp中. 其它一些 ...