Autofac官方文档(二十四)【应用集成之Web Forms】

ASP.NET Web表单集成需要Autofac.Web NuGet包。

Web表单集成为code-behind类提供了依赖注入集成。 它也增加了每个请求生命周期的支持。

本页面介绍了ASP.NET经典的Web表单集成。 如果您正在使用ASP.NET Core,请参阅ASP.NET Core集成页面。

    Quick Start
    Add Modules to Web.config
    Implement IContainerProviderAccessor in Global.asax
    Tips and Tricks
        Structuring Pages and User Controls for DI
        Manual Property Injection
        Explicit Injection via Attributes
        Dependency Injection via Base Page Class
        Custom Dependency Injection Modules
    Example

快速开始

要将Autofac与Web表单集成,您需要引用Web表单集成NuGet包,将模块添加到web.config,并在您的全局应用程序类上实现IContainerProviderAccessor

将模块添加到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>

实现IContainerProviderAccessor:

public class Global : HttpApplication, IContainerProviderAccessor
{ 
  // 持有应用程序容器的提供程序
  static IContainerProvider _containerProvider;

  //将被`Autofac HttpModules`用来解析和注入依赖关系的实例属性。
  public IContainerProvider ContainerProvider
  {
    get { return _containerProvider; }
  }

  protected void Application_Start(object sender, EventArgs e)
  {
    //建立您的应用程序容器并注册您的依赖关系
    var builder = new ContainerBuilder();
    builder.RegisterType<SomeDependency>();
    // ...继续注册依赖关系...

    //完成注册之后,请将注册设置为容器提供者
    _containerProvider = new ContainerProvider(builder.Build());
  }
}

以下各节详细介绍了每个功能的用途以及如何使用它们。

将模块添加到Web.config

Autofac管理组件生命周期的方式和向ASP.NET管道中添加依赖注入的方式是通过使用IHttpModule实现。 您需要在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>

请注意,尽管有两个不同的部分,模块出现在IIS6和IIS7中,但建议您同时使用这两个部分。 即使您的目标部署环境是IIS7,ASP.NET开发人员服务器也会使用IIS6设置。 如果使用IIS Express,它将使用IIS7设置。

你在那里看到的模块做了一些有趣的事情:

  • ContainerDisposalModule让Autofac处理请求处理期间创建的任何组件,只要请求完成。
  • 在页面生命周期执行之前,PropertyInjectionModule将依赖注入到页面中。还提供了一个替代的UnsetPropertyInjectionModule,它只会在具有空值的Web表单/控件上设置属性。(只使用一个或另一个,但不能同时使用)

在Global.asax中实现IContainerProviderAccessor

依赖注入模块期望HttpApplication实例支持IContainerProviderAccessor。下面显示了一个完整的全局应用程序类:

public class Global : HttpApplication, IContainerProviderAccessor
{
  //持有应用程序容器的提供程序
  static IContainerProvider _containerProvider;

  //将被Autofac HttpModules用来解析和注入依赖关系的实例属性。
  public IContainerProvider ContainerProvider
  {
    get { return _containerProvider; }
  }

  protected void Application_Start(object sender, EventArgs e)
  {
    //建立您的应用程序容器并注册您的依赖关系
    var builder = new ContainerBuilder();
    builder.RegisterType<SomeDependency>();
    // ...继续注册依赖关系...

    //完成注册之后,请将注册设置为容器提供商
    _containerProvider = new ContainerProvider(builder.Build());
  }
}

Autofac.Integration.Web.IContainerProvider公开了两个有用的属性:ApplicationContainerRequestLifetime

  • ApplicationContainer是在应用程序启动时构建的根容器。
  • RequestLifetime是基于应用程序容器的组件生命周期作用域,它将在当前Web请求的末尾处理。只要需要手动依赖关系解析/服务查找,就可以使用它。它包含的组件(除了任何单例)将特定于当前请求(这是每个请求生命周期依赖性被解决的地方)。

技巧和窍门

为DI构建页面和用户控件

为了向Web表单页面(System.Web.UI.Page实例)或用户控件(System.Web.UI.UserControl实例)注入依赖项,必须将其依赖项公开为允许设置的公共属性。这使PropertyInjectionModule为您填充这些属性。

确保在应用程序启动时注册您将需要的依赖关系。

var builder = new ContainerBuilder();
builder.RegisterType<Component>().As<IService>().InstancePerRequest();
//...继续注册依赖关系,然后构建容器提供者...
_containerProvider = new ContainerProvider(builder.Build());

然后在你的页面代码隐藏中,为你需要的依赖项创建public get/set属性:

// MyPage.aspx.cs
public partial class MyPage : Page
{
  //该属性将由PropertyInjectionModule为您设置
  public IService MyService { get; set; }

  protected void Page_Load(object sender, EventArgs e)
  {
    //现在您可以使用为您设置的属性
    label1.Text = this.MyService.GetMessage();
  }
}

同样的公共属性注入过程也适用于用户控件 - 只需在应用程序启动时注册组件,并为依赖关系public get/set属性。

在用户控件的情况下,必须注意,如果通过页面请求生命周期的PreLoad步骤创建控件并将其添加到页面的Controls集合,那么只会自动注入属性。在代码中或通过像Repeater这样的模板动态创建的控件在此处将不可见,并且必须手动注入其属性。

手动属性注入

在某些情况下,如在编程创建用户控件或其他对象时,可能需要手动在对象上注入属性。要做到这一点,你需要:

  • 获取当前的应用程序实例。
  • 将其转换为Autofac.Integration.Web.IContainerProviderAccessor
  • 从应用程序实例中获取容器提供者。
  • IContainerProvider获取RequestLifetime,并使用InjectProperties()方法在对象上注入属性。

在代码中,看起来像这样:

var cpa = (IContainerProviderAccessor)HttpContext.Current.ApplicationInstance;
var cp = cpa.ContainerProvider;
cp.RequestLifetime.InjectProperties(objectToSet);

请注意,您需要AutofacAutofac.Integration.Web名称空间来使属性注入工作,因为InjectProperties()Autofac名称空间中的扩展方法。

通过属性显式注入

当向现有应用程序添加依赖项注入时,有时需要区分将注入依赖关系的注入和不注入的Web表单页面。 Autofac.Integration.Web中的InjectPropertiesAttributeAttributedInjectionModule一起帮助实现了这一点。

如果您选择使用AttributedInjectionModule,则不会自动将依赖项注入到公共属性中,除非它们被标记为特殊属性。

首先,从web.config文件中移除PropertyInjectionModule,并将其替换为AttributedInjectionModule

<configuration>
  <system.web>
    <httpModules>
      <!--本部分用于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>
    <!--本部分用于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>

一旦到位,页面和控件将不会默认注入其依赖项。 相反,它们必须用Autofac.Integration.Web.Forms.InjectPropertiesAttributeAutofac.Integration.Web.Forms.InjectUnsetPropertiesAttribute标记。 区别:

  • 如果在Autofac中注册了相关的组件,InjectPropertiesAttribute将始终在页面/控件上设置公共属性。
  • InjectUnsetPropertiesAttribute只会设置页面/控件上的公共属性,如果它们为空,并且关联的组件被注册。
[InjectProperties]
public partial class MyPage : Page
{
  //该属性将由AttributedInjectionModule为您设置
  public IService MyService { get; set; }

  // ...稍后根据需要使用该属性.
}

通过基本页面类的依赖注入

如果您不想使用模块自动注入属性(例如前面提到的AttributedInjectionModulePropertyInjectionModule),则可以通过创建一个在页面的PreInit阶段执行手动属性注入的基本页类,以更人工的方式集成Autofac 请求生命周期。

这个选项允许你从一个普通的基本页面类派生需要依赖注入的页面。 如果只有很少的页面需要依赖注入,并且不需要管道中的AttributedInjectionModule,则可能需要执行此操作。 (您仍然需要ContainerDisposalModule。)如果您的页面少于几页,则可以考虑通过属性显式注入。

protected void Page_PreInit(object sender, EventArgs e)
{
  var cpa = (IContainerProviderAccessor)HttpContext.Current.ApplicationInstance;
  var cp = cpa.ContainerProvider;
  cp.RequestLifetime.InjectProperties(this);
}

自定义依赖注入模块

如果提供的PropertyUnset PropertyAttributed依赖注入模型不合适,那么创建自定义注入行为是非常容易的。 简单地继承Autofac.Integration.Web.DependencyInjectionModule并在Web.config中使用结果。

有一个抽象成员来实现:

protected abstract IInjectionBehaviour GetInjectionBehaviourForHandlerType(Type handlerType);

返回的IInjectionBehaviour可以是预定义的NoInjectionPropertyInjectionUnsetPropertyInjection属性之一; 或IInjectionBehaviour接口的自定义实现。

示例

有一个示例项目显示了Autofac示例存储库中的ASP.NET Web表单集成。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值