惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - Franky
Apple Machine Learning Research
Apple Machine Learning Research
月光博客
月光博客
Vercel News
Vercel News
Recent Announcements
Recent Announcements
B
Blog RSS Feed
Y
Y Combinator Blog
M
MIT News - Artificial intelligence
MongoDB | Blog
MongoDB | Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
雷峰网
雷峰网
D
Docker
Jina AI
Jina AI
IT之家
IT之家
人人都是产品经理
人人都是产品经理
L
LangChain Blog
G
Google Developers Blog
Google DeepMind News
Google DeepMind News
MyScale Blog
MyScale Blog
博客园 - 叶小钗
The GitHub Blog
The GitHub Blog
The Cloudflare Blog
A
About on SuperTechFans
Hugging Face - Blog
Hugging Face - Blog

博客园 - 十三

ASP.NET MVC5学习笔记之Action参数模型绑定之模型元数据和元数据提供 ASP.NET MVC5学习笔记之Action参数模型绑定值提供体系 ASP.NET MVC5学习笔记之Action参数模型绑定基本过程 ASP.NET MVC5学习笔记之Filter提供体系 ASP.NET MVC5学习笔记之Filter基本介绍 ASP.NET MVC5学习笔记之Controller执行ControllerDescriptor和ActionDescriptor ASP.NET MVC5学习笔记之Controller同步执行架构分析 ASP.NET MVC4学习笔记之Controller的激活 ASP.NET MVC4学习笔记路由系统实现 ASP.NET MVC4学习笔记路由系统概念与应用篇 ASP.NET MVC4学习笔记之总体概述 Web Capacity Analysis Tool 压力测试工具使用笔记 WCF完全解析读书笔记第2章地址 CLR via C# 混合线程同步构造 CLR via C# I/O基元线程同步构造 CLR via C# 计算限制的异步操作读书笔记 CLR via C# 线程基础知识读书笔记 CLR via C# 序列化读书笔记 CLR via C# 内存管理读书记
ASP.NET MVC4学习笔记之Controller激活的扩展
十三 · 2014-03-22 · via 博客园 - 十三

一. 为什么要进行扩展

  在前面的分析中,我们知道默认的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中直接调用一个或多个服务类处理。具体使用那一种模式,应根据你的项目情况来决定,这里不展开细说了。

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