一. 为什么要进行扩展

  在前面的分析中,我们知道默认的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. [HDU 5090] Game with Pearls (贪心)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5090 题目大意:给你n个数,问你给若干个数增加c*k(c>=0)能否组成1,2,3,4,5,.. ...

  2. Linux安装MySQL的两种方法

    转载:http://blog.csdn.net/superchanon/article/details/8546254/ 1.       运行平台:CentOS 6.3 x86_64,基本等同于RH ...

  3. ASP.NET MVC 之 View 测试

    项目又出问题了!手贱了一下,使用某个工具整理了一下 View 中的内容,不经意之间,将 View 的输出中大小写不小心搞错了,导致输出的内容没有办法正常解析. 这种问题太隐蔽了,下次再遇到怎么办呢? ...

  4. C#将C++动态库的回调函数封装成事件

    关于C#调用C++动态库的文章很多,调用动态库中回调函数的方法也不在少数.但大多数调用回调函数的方法依然保留了C++的语法特点. 比如有一段C++的回调函数代码,为了表达它的意思,我把注释也粘贴了进来 ...

  5. 利用Meida Service的Java SDK来调用Azure Media Services的Index V2实现视频字幕自动识别

    Azure Media Services新的Index V2 支持自动将视频文件中的语音自动识别成字幕文件WebVtt,非常方便的就可以跟Azure Media Player集成,将一个原来没字幕的视 ...

  6. 多文件目录下makefile文件递归执行编译所有c文件

    首先说说本次嵌套执行makefile文件的目的:只需make根目录下的makefile文件,即可编译所有c文件,包括子目录下的. 意义:自动化编译行为,以后编译自己的c文件时可把这些makefile文 ...

  7. sass sublime text 2 gulp ionic

    sass 安装1.全局安装 sass 我的Mac 所以不用再安装Ruby ,直接在终端输入 gem install sass 然后在终端中输入 sass -v 出现 Sass 3.4.8 (selec ...

  8. iptable nat网关

    echo "1" > /proc/sys/net/ipv4/ip_forward iptables -t nat -A POSTROUTING -s 192.168.1.0/ ...

  9. 在ax中怎么对enum类型循环取其中每一个值

    static void test(Args _args) { DictEnum dictEnum; int i,nextPos; EnumId enumId; ; enumId = EnumNum(S ...

  10. CSS阻止页面双击选中文本

    转载自:w3cui 在双击左右箭头,快速切换图片滚动时,会选择附近区域的文字,感觉不是很好,今天在同事在分享时,讲到了这个问题, 试了一下,不错,解决了问题IE及Chrome下的方法一样,对相应的元素 ...