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

你可能感兴趣的:(controller)