一. 为什么要进行扩展

  在前面的分析中,我们知道默认的Controller激活系统只能实例化无参构造函数的Controller类型,但在某些情况一下,我们希望某些服务的实例能够自动注入到Controller实例中,从而达到服务接口和实现的隔离,减小重复的代码,提高系统的可维护性和灵活性。也就是说我们希望在Controller激活中引入依赖注入。关于依赖注入的概念这里就不解释了,请自行查询相关的资料。基于.net依赖注入框架也有很多,下面的例子主要使用微软企业库的Unity。

  在上一节的分析中,我们知道Controller的激活实际是包括获取IControllerFacotry和IController实例, 在这两个级别都可以引入扩展实现在我们的目的,现在具体来看一下。

一.实列化IControllerFactory  Level

  在这个Level我们知道了路由系统提供的路由信息,当然甚至可以从头到尾自定义实现一个ControllerFactory,包括Controller类型的确定和实例化,但通常没什么必要。我们目标是在Controller实例化阶段注入服务实例,主要还是在Controller实例化阶段。

二. 实列化Controller Level

  在这一阶段,我们已经确定Controller的类型,通过上一节的分析,有三个点我们可以引入依赖注入。我们假设有一个要显示所有Customer信息的页面,在其中应用了仓储模式,在CustomerController实例化进自动注入仓储的实例。

1. 继承DefaultControllerFactory,重写GetControllerInstance方法。大概的代码如下:

  

public class UnityControllerFactory : DefaultControllerFactory

  {
    public IUnityContainer Container
    {
      get;
      private set;
    }     public UnityControllerFactory(IUnityContainer container)
    {
      this.Container = container;
    }     protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
      return (IController)this.Container.Resolve(controllerType);
    }
  }

  然后在Global.asax的Application_Start中注册

private void RegisterUnityControllerFactory()

  {
    IUnityContainer container = new UnityContainer();
    container.RegisterType<ICustomerRepository, CustomerRepository>();
    ControllerBuilder.Current.SetControllerFactory(new UnityControllerFactory(container));
  }

  2. 自定义实现IControllerActivator。大概的代码如下:

  

public class UnityControllerActivator : IControllerActivator

  {
    public IUnityContainer Container
    {
      get;
      private set;
    }     public UnityControllerActivator(IUnityContainer c)
    {
      this.Container = c;
    }     public IController Create(RequestContext requestContext, Type controllerType)
    {
      return (IController)this.Container.Resolve(controllerType);
    }
  }

  注册代码:

  

 private void RegisterUnityControllerActivator()

   {
    IUnityContainer container = new UnityContainer();
    container.RegisterType<ICustomerRepository, CustomerRepository>();
    ControllerBuilder.Current.SetControllerFactory(new DefaultControllerFactory(new UnityControllerActivator(container)));
  }

  3.自定义实现全局的IDependencyResolver

public class UnityDependencyResolver : IDependencyResolver
{
private IUnityContainer Container
{
get;
set;
} public UnityDependencyResolver()
{
this.Container = new UnityContainer();
} public UnityDependencyResolver RegisterType<TFrom, TTo>() where TTo : TFrom
{
this.Container.RegisterType<TFrom, TTo>();
return this;
} public object GetService(Type serviceType)
{
try
{
return this.Container.Resolve(serviceType);
}
catch(ResolutionFailedException)
{
return null;
}
} public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return this.Container.ResolveAll(serviceType);
}
catch (ResolutionFailedException)
{
return null;
}
}

    注册代码:

private void SetDependencyResolver()
{
UnityDependencyResolver resolver = new UnityDependencyResolver();
resolver.RegisterType<ICustomerRepository, CustomerRepository>();
DependencyResolver.SetResolver(resolver);
}

三.真的要扩展吗?

  天下没有完美的东西,引入一样东西我们必须要充分认识它的优势,也要认清它的副作用。在实际项目中,个人觉得大部分情况是没必要在Controller这个Level引入依赖注入,在Controller的Action中,通常我们要调用业务逻辑服务,业务逻辑的服务接口通常是没必要再引入一层另外的抽象。

  另外,在这里大致总结一下,在Action中大概有两种方式来调用业务逻辑,一种利用Command模式,即把每个Action 对一个Command,在Command中再调用业务逻辑服务.一种是每个Controller包含一个或多个粗粒度的业务包装服务类,每个Action中直接调用一个或多个服务类处理。具体使用那一种模式,应根据你的项目情况来决定,这里不展开细说了。

最后所有的测试代码可以在这里下载http://files.cnblogs.com/jjyjjyjjy/TestAsp_Net_Mvc_ControllerActivator_DI.rar

ASP.NET MVC4学习笔记之Controller激活的扩展的更多相关文章

  1. ASP.NET MVC4学习笔记之Controller的激活

    一. 高层相关类说明 当路由系统根据请求Url收集路由信息后,下一步就要将路由信息传给Controller激活系统,Controller激活系统负责实现了IController接口的Controlle ...

  2. ASP.NET MVC 学习笔记-7.自定义配置信息 ASP.NET MVC 学习笔记-6.异步控制器 ASP.NET MVC 学习笔记-5.Controller与View的数据传递 ASP.NET MVC 学习笔记-4.ASP.NET MVC中Ajax的应用 ASP.NET MVC 学习笔记-3.面向对象设计原则

    ASP.NET MVC 学习笔记-7.自定义配置信息   ASP.NET程序中的web.config文件中,在appSettings这个配置节中能够保存一些配置,比如, 1 <appSettin ...

  3. asp.net mvc4 学习笔记一(基本原理)

    做了8年的asp.net webform,用过MVVM但还没用过MVC , 虽然项目不用MVC,但是还是想了解一下,今天第二天学习,以下是学习心得. VS2012默认带有asp.net mvc3和as ...

  4. ASP.NET MVC4学习笔记路由系统概念与应用篇

    一.概念 1.路由是计算机网络中的一个技术概念,表示把数据包从一个网段转发至另一网段.ASP.NET中的路由系统作用类似,其作用是把请求Url映射到相应的"资源"上,资源可以是一段 ...

  5. ASP.NET MVC4学习笔记之总体概述

    断断续续使用ASP.NET MVC框架也有一年多了,也算积累了一些经验,唉,一直想写一些笔记好好总结一下,人太懒不想动笔,今天终于决定开始.希望自己能坚持下去. 这篇文章大体介绍ASP.NET MVC ...

  6. ASP.NET MVC5学习笔记之Controller同步执行架构分析

    在开始之前,声明一下,由于ASP.NET MVC5正式发布了,后面的分析将基于ASP.NET MVC5最新的源代码.在前面的内容我们分析了怎样根据路由信息来确定Controller的类型,并最终生成C ...

  7. ASP.NET MVC4学习笔记路由系统实现

    一.路由实现 路由系统实际是一个实现了ASP.NET IHttpModule接口的模块,通过注册HttpApplication的PostResolveRequestCache 事件对Url路由处理.总 ...

  8. ASP.NET MVC4学习笔记

    一.MVC简介

  9. ASP.NET MVC5学习笔记之Controller执行ControllerDescriptor和ActionDescriptor

    一. ControllerDescriptor说明 ControllerDescriptor是一个抽象类,它定义的接口代码如下: public abstract class ControllerDes ...

随机推荐

  1. oracle 11g 服务端下载地址及安装说明

        oracle 11g 服务端下载地址及安装说明         分类:             Oracle              2013-11-17 19:40     988人阅读  ...

  2. convert NameValueCollection/Dictionary<string, object> to JSON string

    public static class WebExtension { public static T Decode<T>(this RequestBase res) { Type type ...

  3. OC基础(19)

    类扩展(Class Extension) Block基本概念 typedef和Block Block注意事项 *:first-child { margin-top: 0 !important; } b ...

  4. XAML学习笔记

         XAML是用于实例化.NET对象的标记语言,主要用于构造WPF界面.不同于WPF之前的Windows编程技术(WinForm,MFC及win32sdk),在WPF之中界面主要是在XAML中添 ...

  5. 走出测试,走向CEO

    飞测说:大家好,我们又见面了,我是黑夜小怪.不巧,今晚加班回来路上,湿身了,淋了个落汤鸡,不过明天也许可以看海了,也就呵呵了,原本想回来后聊些技术的,现在突然想先聊聊我的一些想法,仅供交流. 走出测试 ...

  6. C/c++笔试经典程序(一)

    1.输出结果比较 1) 输出结果:21 2) 输出结果:12.虽然循环只进行了一次,但是对!X++来说,X还是进行了自加运算. 2.指针运算 输出结果8,8.程序运行时,printf语句是从右往左进行 ...

  7. XGBoost参数

    XGBoost参数 转自http://blog.csdn.net/zc02051126/article/details/46711047 在运行XGboost之前,必须设置三种类型成熟:general ...

  8. django中添加用户

    在django中添加用户,直接在auth_user表中添加会有问题,因为这里密码是加密的,可以通过manage.py shell加入 创建User: 1 >>> from djang ...

  9. 学习记录 java随机数的产生机制

    java 随机数 一.在j2se里我们可以使用Math.random()方法来产生一个随机数,这个产生的随机数是0-1之间的一个double,我们可以把他乘以一定的数,比如说乘以100,他就是个100 ...

  10. new 、operator new 和 placement new

    一.原生operator new 我们先从原生operator new开始.考虑如下代码,它用来分配5个int型的空间并返回指向他们的指针[1]: int* v = static_cast<in ...