咱们在项目中很早就开始使用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
但愿对你有帮助,若有错误,欢迎指出!