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 ...
随机推荐
- centos vncviewer
CentOS6.5 安装vncserver实现图形化访问 一. 安装gnome图形化桌面 #yum groupinstall -y "X Window System" #yum ...
- HTTP.ContentType
1. multipart/x-mixed-replace http://blog.dubbelboer.com/2012/01/08/x-mixed-replace.html
- fedora 安装gdal
hese steps worked for me on a Fedora system: 1.) download the 3 files related to oracle instant clie ...
- maven 单元测试 ( http://www.cnblogs.com/qinpengming/p/5225380.html )
对junit单元测试的报告:类似这样的结果 ------------------------------------------------------- T E S T S ----------- ...
- Java中关键字static的使用
static 关键字 1).static只能修饰成员变量或成员方法,所有非静态是对象相关的,所有静态是类相关的. 2)被static修饰的成员变量成员方法独立于该类的任何对象,它不依赖类的特定的实例, ...
- Netty 源码 Channel(二)核心类
Netty 源码 Channel(二)核心类 Netty 系列目录(https://www.cnblogs.com/binarylei/p/10117436.html) 一.Channel 类图 二. ...
- js、css、img等浏览器缓存问题的2种解决方案
转:http://www.jb51.net/article/42339.htm 浏览器缓存的意义在于提高了执行效率,但是也随之而来带来了一些问题,导致服务端修改了js.css,客户端不能更新,下面有几 ...
- Partition Array into Disjoint Intervals LT915
Given an array A, partition it into two (contiguous) subarrays left and right so that: Every element ...
- spring学习 十 schema-based 前置后后置通知
spring 提供了 2 种 AOP 实现方式:(1)Schema-based ,(2)AspectJ Schema-based:每个通知都需要实现接口或类,配置 spring 配置文件时在<a ...
- Tarjan 割点,桥
/* ggg ggg ggggggg ggggggg ggggggggggggggggggg ggggggggggggggg ggggggggggg ggggggg ggg g */ /* gyt L ...