zoukankan      html  css  js  c++  java
  • ASP.NET MVC4学习笔记之Controller激活的扩展

    一. 为什么要进行扩展

      在前面的分析中,我们知道默认的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

  • 相关阅读:
    configure: error: C++ preprocessor "/lib/cpp" fails sanity check See `config.log' for more details
    php7安装swoole
    Navicat 连接Mysql 8.0以上版本报错1251的详细解决方案
    1130
    linux中的 /etc/profile文件centos7
    linux安装php遇到的No package 'sqlite3' found,解决方法:
    ll: command not found
    每日一题 为了工作 2020 0325 第二十三题
    每日一题 为了工作 2020 0324 第二十二题
    每日一题 为了工作 2020 0323 第二十一题
  • 原文地址:https://www.cnblogs.com/jjyjjyjjy/p/3617583.html
Copyright © 2011-2022 走看看