咱們在項目中很早就開始使用autofac,也覺得知道與mvc和webapi集成的作法。web
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中經過構造函數注入,這沒必要多說。api
可是,在實際項目需求的時候,有些地方不方便使用構造函數,或者說就要使用服務定位IContainer.Resolve(ServiceType)的方式來得到服務的實例。mvc
曾經在項目中看到過有人經過把Container設區全局靜態變量來得到對象容器。這個方式在Local的狀況下,不會有太大問題。在Mvc中,容器DependencyResolver.Current自己也是經過儘可能變量來實現的。ide
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一個服務,那麼如何來指定容器呢?ui
帶着問題,咱們先來看看DependencyResolver.Current和GlobalConfiguration.Configuration.DependencyResolver,經過一組實驗來對比一下:spa
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的容器code
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 } }
咱們在HomeContorller中經過三種不一樣方法來獲取對象,目的是三個對象都應該是同一個對象,結果也符合預期,再看看WebApi的:對象
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來獲取的對象,居然不等於構造函數解析出來的對象,有點毀三觀。說明它並非當前上下文的對象,也就是說這個對象的生命週期不在控制範圍內。blog
那麼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
但願對你有幫助,若有錯誤,歡迎指出!