zoukankan      html  css  js  c++  java
  • 转:autofac在mvc和webapi集成的做法

    本文转自:http://www.cnblogs.com/Hai--D/p/5992573.html

    var builder = new ContainerBuilder();
    
    // Mvc Register
    builder.RegisterControllers(Assembly.GetExecutingAssembly()).AsSelf().PropertiesAutowired();
    builder.RegisterFilterProvider();
    builder.RegisterType<UserService>().As<IUserService>().InstancePerLifetimeScope();
    
    //WebApi Register
    builder.RegisterApiControllers(Assembly.GetExecutingAssembly()).AsSelf().PropertiesAutowired();
    builder.RegisterWebApiFilterProvider(GlobalConfiguration.Configuration);
    builder.RegisterWebApiModelBinderProvider();
    
    var container = builder.Build();
    
    // Set the dependency resolver for Web API.
    var webApiResolver = new AutofacWebApiDependencyResolver(container);
    GlobalConfiguration.Configuration.DependencyResolver = webApiResolver;
    
    // Set the dependency resolver for MVC.
    var resolver = new AutofacDependencyResolver(container);
    DependencyResolver.SetResolver(resolver);
    

      

    在实际Controller和ApiController中通过构造函数注入,这不必多说。

    但是,在实际项目需求的时候,有些地方不方便使用构造函数,或者说就要使用服务定位IContainer.Resolve(ServiceType)的方式来获得服务的实例。

    曾经在项目中看到过有人通过把Container设区全局静态变量来获得对象容器。这个方式在Local的情况下,不会有太大问题。在Mvc中,容器DependencyResolver.Current本身也是通过尽量变量来实现的。

     public class DependencyResolver
        {
            public DependencyResolver();
    
            public static IDependencyResolver Current { get; }
        ...
        }
    

      

    但是和C端不同的是,Web服务是基于请求的,autofac内部的InstancePerLifetimeScope,InstancePerHttpRequest,InstancePerApiRequest等都是基于每次请求的Scope,而静态的Container明显生命周期不符合。

    所以我们写代码的时候都是通过DependencyResolver.Current.GetService()和GlobalConfiguration.Configuration.DependencyResolver.GetService()来分别获取Mvc和WebApi的对象。那么问题来了,我有一段业务逻辑在BLL中,Mvc和WebApi可以都调用到,其中需要Resolve一个服务,那么如何来指定容器呢?

    带着问题,我们先来看看DependencyResolver.Current和GlobalConfiguration.Configuration.DependencyResolver,通过一组实验来对比一下:

     public class WebApiApplication : System.Web.HttpApplication
        {
            public static System.Web.Mvc.IDependencyResolver mvcResolver;
            public static System.Web.Http.Dependencies.IDependencyResolver apiResolver;
    
            protected void Application_Start()
            {
                ...
           builder.RegisterType<UserService>().As<IUserService>().InstancePerLifetimeScope();
    
                 // Set the dependency resolver for Web API.
                var webApiResolver = new AutofacWebApiDependencyResolver(container);
                apiResolver = webApiResolver;
                GlobalConfiguration.Configuration.DependencyResolver = webApiResolver;
    
                // Set the dependency resolver for MVC.
                var resolver = new AutofacDependencyResolver(container);
                mvcResolver = resolver;
                DependencyResolver.SetResolver(mvcResolver);
              }
        }
                
       public interface IUserService
        {
        }
    
        public class UserService : IUserService
        {
        }
    

      我们分别定义了两个静态变量mvcResolver和apiResolver来存储两个不同的容器,并注册了一组服务,指定其生命周期为InstancePerLifetimeScope,先看看Mvc的容器

     public class HomeController : Controller
        {
            IUserService _userservice;
    
            public HomeController(IUserService userService)
            {
                _userservice = userService;
                var a = DependencyResolver.Current.GetService<IUserService>();
                var b = WebApiApplication.mvcResolver.GetService<IUserService>();
                var c1 = ReferenceEquals(userService, a);   //true
                var c2 = ReferenceEquals(userService, b);   //true
                var c3 = ReferenceEquals(b, a);             //true
            }
        }
    
     public class ValuesController : ApiController
        {
            IUserService _userservice;
    
            public ValuesController(IUserService userService)
            {
                _userservice = userService;
                var a = GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IUserService));
                var b = WebApiApplication.apiResolver.GetService(typeof(IUserService));
                var c1 = ReferenceEquals(userService, a);   //false
                var c2 = ReferenceEquals(userService, b);   //false
                var c3 = ReferenceEquals(b, a);             //true
            }
        }
    

      

    发现通过GlobalConfiguration.Configuration.DependencyResolver来获取的对象,竟然不等于构造函数解析出来的对象,有点毁三观。说明它并不是当前上下文的对象,也就是说这个对象的生命周期不在控制范围内。

    那么Mvc和WebApi可不可以用同一个容器来指定呢?

    我们先来看看stackoverflow上的这篇文章:Is it possible to configure Autofac to work with ASP.NET MVC and ASP.NET Web Api

    其实Mvc和WebApi分别是两个独立的依赖解析器,这点没什么问题,一个是System.Web.Mvc.IDependencyResolver另一个是System.Web.Http.Dependencies.IDependencyResolver,两个互相不串。

    最后,一个很重要的对象来了,那就是Autofac.IComponentContext,它就是解析的上下文,通过它来解析的对象是符合当前上下文的,我们再来看看之前的例子:

    public class HomeController : Controller
        {
            IUserService _userservice;
    
            public HomeController(IUserService userService, IComponentContext com)
            {
                _userservice = userService;
                var a = DependencyResolver.Current.GetService<IUserService>();
                var b = WebApiApplication.mvcResolver.GetService<IUserService>();
                var d = com.Resolve<IUserService>();
                var d1 = ReferenceEquals(userService, d);   //true
                var c1 = ReferenceEquals(userService, a);   //true
                var c2 = ReferenceEquals(userService, b);   //true
                var c3 = ReferenceEquals(b, a);             //true
            }
        }
    

      

    //WebApi:
    public class ValuesController : ApiController
        {
            IUserService _userservice;
    
            public ValuesController(IUserService userService, IComponentContext  com)
            {
                _userservice = userService;
                var a = GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IUserService));
                var b = WebApiApplication.apiResolver.GetService(typeof(IUserService));
                var d = com.Resolve<IUserService>();
                var d1 = ReferenceEquals(userService, d);   //true
                var c1 = ReferenceEquals(userService, a);   //false
                var c2 = ReferenceEquals(userService, b);   //false
                var c3 = ReferenceEquals(b, a);             //true
            }
        }
    

      

    参考:

    ASP .Net 4 Web Api RC + Autofac manual resolving

    希望对你有帮助,如有错误,欢迎指出! 用属性自动注入需要是public,

    如果,能支持 protected 注入,那就完美了

  • 相关阅读:
    Linux进程间通信分类 以及 pipe的原理实现
    单链表的快速排序
    再谈二分查找
    数据库范式
    二分查找法浅析
    C# Observer设计模式
    C# 交错数组浅析
    C语言初学 数学中带根号的复杂计算问题
    C语言初学 计算三角形面积问题
    C语言初学 简单定义圆的面积计算问题
  • 原文地址:https://www.cnblogs.com/fer-team/p/6432439.html
Copyright © 2011-2022 走看看