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 ...
随机推荐
- 常用MFC宏
最近我在用MFC开发一个智能家居监控平台的软件(用到了MSCOMM串口通信控件),当我通过在一个对话框类A中定义另一个对话框类B的对象访问B的public成员时,提示不可访问.后来经过多天的向朋友求救 ...
- POJ 3169.Layout 最短路
Layout Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 11612 Accepted: 5550 Descripti ...
- readv writev示例程序
当 readv() 时候,需要程序自己提供space,接收数据. #include <stdio.h> #include <stdlib.h> #include <str ...
- ApplicationContext(三)BeanFactory 初始化
ApplicationContext(三)BeanFactory 初始化 上节我们提到容器初始化的第一步首先进行了属性的检验,下面就要开始第二步:进行 beanFactory 的初始化工作了. App ...
- JSR 规范目录
JSR 规范目录 一.Servlet 规范 1.1 Servlet 2.x 规范 1.2 Servlet 3.x 规范 - 注解和异步请求规范 每天用心记录一点点.内容也许不重要,但习惯很重要!
- rapidjson 的封装学习
#pragma once #include "Util.h" #include "rapidjson/writer.h" #include "rapi ...
- rowspan和colspan的区别粗解
rowspan和colspan是我们初学HTML表格中会在做一些特殊表格中遇到.其常在td中添加. rowspan的作用是指定纵向所跨越单元格的行数. 如下效果. colspan的作用是指定单元格横向 ...
- Emacs, Nano, or Vim 编辑器“三剑客”
# Vim 强大,多种模式相互切换,不同于传统“录入式“写东西 对后续两个编辑器不熟悉 # nano 退出ctrl + x http://man.linuxde.net/nano # emacs ht ...
- 日志分析工具、日志管理系统、syslog分析
日志分析工具.日志管理系统.syslog分析 系统日志(Syslog)管理是几乎所有企业的重要需求.系统管理员将syslog看作是解决网络上系统日志支持的系统和设备性能问题的关键资源.人们往往低估了对 ...
- 20175316盛茂淞-Java第1周学习总结
20175316盛茂淞 2018-2019-2 <Java程序设计>第1周学习总结 教材学习内容总结 Java入门 1.Java简介(地位,特点) 2.安装JDK,设置系统环境 3.编译J ...