autofac.web通常是对Page或用户/自定义控件做属性注入
public class Article:System.Web.UI.Page { public IArticleService ArticleService{get;set;} //PageLoad事件或其它代码地方直接调用ArticleService.Get.... }
1 安装autofac.web nuget方式
2 web.config中做配置
<configuration> <system.web> <httpModules> <!-- This section is used for IIS6 --> <add name="ContainerDisposal" type="Autofac.Integration.Web.ContainerDisposalModule, Autofac.Integration.Web"/> <add name="PropertyInjection" type="Autofac.Integration.Web.Forms.PropertyInjectionModule, Autofac.Integration.Web"/> </httpModules> </system.web> <system.webServer> <!-- This section is used for IIS7 --> <modules> <add name="ContainerDisposal" type="Autofac.Integration.Web.ContainerDisposalModule, Autofac.Integration.Web" preCondition="managedHandler"/> <add name="PropertyInjection" type="Autofac.Integration.Web.Forms.PropertyInjectionModule, Autofac.Integration.Web" preCondition="managedHandler"/> </modules> </system.webServer> </configuration>
ContainerDisposalModule在页面释放请求结束时释放autofac创建的相关对象和autofacScope
PropertyInjectionModule 猜测这个是在页面创建后做依赖注入的。这里也可以用另一个类型UnsetPropertyInjectionModule,唯一的区别是若我们已经自己在构造函数中对依赖的属性赋值了,前者的方式是继续依赖注入,后者则不会。二者只能选其一
3 实现IContainerProviderAccessor
有时候我们想在代码中手动从容器中解析指定接口或类型,此时我们需要访问容器或生命周期(全局容器和生命周期请看相关文章),实现IContainerProviderAccessor的目的就是给我们提供一个访问容器或生命周期的一个点
autofac中通常让Global来实现这个接口
public class Global : HttpApplication, IContainerProviderAccessor { // Provider that holds the application container. static IContainerProvider _containerProvider; // Instance property that will be used by Autofac HttpModules // to resolve and inject dependencies. public IContainerProvider ContainerProvider { get { return _containerProvider; } } protected void Application_Start(object sender, EventArgs e) { // Build up your application container and register your dependencies. var builder = new ContainerBuilder(); builder.RegisterType<SomeDependency>(); // ... continue registering dependencies... // Once you're done registering things, set the container // provider up with your registrations. _containerProvider = new ContainerProvider(builder.Build()); } }
这样我们在代码中可以访问全局容器或生命周期了
var cpa = (IContainerProviderAccessor)HttpContext.Current.ApplicationInstance; var cp = cpa.ContainerProvider; cp.RequestLifetime....//当前请求生命周期 cp.ApplicationContainer //全局容器
4.1 自动注入
public class Article:System.Web.UI.Page { public IArticleService ArticleService{get;set;} //PageLoad事件或其它代码地方直接调用ArticleService.Get.... }
注意:若我们的用户控件也注册到了autofac,那么也会做依赖注入,但是若我们通过代码的方式或类似Repeater遍历创建的用户控件都不会做自动注入 ,此时可以参看下面的手动注入
4.2 手动注入
var cpa = (IContainerProviderAccessor)HttpContext.Current.ApplicationInstance; var cp = cpa.ContainerProvider; cp.RequestLifetime.InjectProperties(objectToSet);
4.3 选择性注入
有时候(比如讲autofac添加到现有的项目中),我们的有暴露的属性,但是有的我们需要注入 有的不需要注入 怎么办? 使用另一个注入HttpModule,配合Attribute来选择性注入
<configuration> <system.web> <httpModules> <!-- This section is used for IIS6 --> <add name="ContainerDisposal" type="Autofac.Integration.Web.ContainerDisposalModule, Autofac.Integration.Web"/> <add name="AttributedInjection" type="Autofac.Integration.Web.Forms.AttributedInjectionModule, Autofac.Integration.Web"/> </httpModules> </system.web> <system.webServer> <!-- This section is used for IIS7 --> <modules> <add name="ContainerDisposal" type="Autofac.Integration.Web.ContainerDisposalModule, Autofac.Integration.Web" preCondition="managedHandler"/> <add name="AttributedInjection" type="Autofac.Integration.Web.Forms.AttributedInjectionModule, Autofac.Integration.Web" preCondition="managedHandler"/> </modules> </system.webServer> </configuration>
此时所有页面公开的属性默认情况下不会被注入,除非添加InjectPropertiesAttribute或InjectUnsetPropertiesAttribute,用户控件也一样
4.4 不使用HttpModule方式注入
HttpModule的方式对所有页面、所用用户控件都会做注入。若我们只想对部分页面做注入,可以通过定义基类Page的方式实现
protected void Page_PreInit(object sender, EventArgs e) { var cpa = (IContainerProviderAccessor)HttpContext.Current.ApplicationInstance; var cp = cpa.ContainerProvider; cp.RequestLifetime.InjectProperties(this); }
4.5 自定义依赖注入Module
定义一个HttpModule实现Autofac.Integration.Web.DependencyInjectionModule
protected abstract IInjectionBehaviour GetInjectionBehaviourForHandlerType(Type handlerType);
The returned IInjectionBehaviour can be one of the predefined NoInjection, PropertyInjection, or UnsetPropertyInjection properties; or a custom implementation of the IInjectionBehaviour interface.