【问题标题】:Autofac Webform Integration: Manual Property InjectionAutofac Webform 集成:手动属性注入
【发布时间】:2013-08-29 10:37:27
【问题描述】:

考虑一下这个用于 webform MVP 风格应用程序的 autofac 注册模块,我通过提供一些参数依赖来注册几个组件。

public class SampleModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterType<FooService>().As<IFooService>();
        builder.Register<FooPresenter>((c, p) => 
                            new FooPresenter(p.Named<IFooView>("view"),
                                             c.Resolve<IFooService>(p),
                                             p.Named<string>("connectionString")))
                                             .InstancePerHttpRequest();
        base.Load(builder);
    }
}

在页面中,我可以使用如下代码解析类型:

protected override void OnPreInit(EventArgs e)
{
    base.OnPreInit(e);
    var cpa = (IContainerProviderAccessor) HttpContext.Current.ApplicationInstance;
    var cp = cpa.ContainerProvider;

    // Resolve presenter
    var presenter = cp.RequestLifetime.Resolve<FooPresenter>(
                new NamedParameter[] 
                {
                    new NamedParameter("connectionString", "xyz"), 
                    new NamedParameter("view", this)
                });
}

但我真的很想使用属性注入并在该级别管理对参数的依赖;例如这样的事情:

public FooPresenter Presenter { get; set; }

protected override void OnPreInit(EventArgs e)
{
    base.OnPreInit(e);
    var cpa = (IContainerProviderAccessor) HttpContext.Current.ApplicationInstance;
    var cp = cpa.ContainerProvider;

    // Parameters bindings?
    cp.RequestLifetime.InjectProperties(this);
}

我可以在 Autofac 上利用什么?提前致谢。

【问题讨论】:

    标签: dependency-injection autofac


    【解决方案1】:

    是的,有 ASP.NET 集成可以注入页面级属性。

    请参阅此处的“将模块添加到 Web.config”部分:

    http://code.google.com/p/autofac/wiki/AspNetIntegration

    编辑:对不起,误解了这个问题。我现在看到您不是在询问是否可以使用属性注入,而是在询问如何将其与命名参数结合使用。

    我将做出一个推论,并说您需要命名参数的原因仅仅是为了将视图传递给演示者。连接字符串不应该是页面的责任;您可能可以在 SampleModule 上创建一个属性并从那里读取它。

    我有一种首选的 MVP/Autofac 方法,该方法已经过多年的实战考验。它很干净,提供了一些不错的扩展点,并且保持页面相对没有实现细节。您可以在我对这个问题的回答中找到概述:

    Injecting Lower Layer Dependency in Presenter in an ASP.NET MVP Application

    【讨论】:

    • 抱歉,我的问题不太清楚。我这里要解决的问题是如何在使用autofac的属性注入功能时绑定命名参数。
    • 感谢 Bryan,感谢您为演示者/视图链接提供的巧妙解决方案。没错,连接参数实际上是演示者的虚假依赖项(应用程序的遗留部分将其存储在 Application 对象中)。无论如何,我认为在 Autofac 中拥有一种在属性注入场景中绑定参数的方法应该是有益的;就像 Resolve 方法实际上通过在其重载上使用 IEnumerable 所做的那样。
    • 我明白了。因为 ASP.NET 创建了页面实例,所以您也不能使用像 OnActivating 这样的生命周期事件来获得优势。在某些时候,您需要直接引用容器,就像您在 OnPreInit 中所做的那样;如果要使用参数,则必须自己解析和设置属性,而不是依赖InjectProperties,即Presenter = cp.RequestLifetime.Resolve&lt;FooPresenter&gt;(...parameters...);
    • 如果我需要绑定参数,这实际上是问题的症结所在:必须使用 Resolve 回到服务定位器模式,而不是简单地要求容器在属性级别注入依赖项。
    • 对。我表示它可能是您唯一的选择,因为 ASP.NET 限制了您的选择。我认为没有办法告诉 Autofac 关于 InjectProperties 调用中的参数,这是我可以看到这个工作的唯一方法。通常参数在一个Resolve 调用的范围内,但对于属性,可能有很多参数。我不知道你怎样才能摆脱 SL。
    【解决方案2】:

    这在 Autofac 中有效并且是自动的

    <Autofac.Integration.Web.Forms.InjectUnsetProperties()>
    Public MustInherit Class ViewBasePage(Of TPresenter As BasePresenter(Of TView, TPresenter), TView As {IView, Class})
        Inherits System.Web.UI.Page
        Implements IView
    
    Protected _presenter As TPresenter
    Private _factory As Func(Of TView, TPresenter)
    
    Public Property PresenterFactory As Func(Of TView, TPresenter)
       Get
          Return _factory
       End Get
       Set(value As Func(Of TView, TPresenter)
          _factory = value
    
          _presenter = _factory(DirectCast(DirectCast(Me, IView), TView))
       End Set
     End Property
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-01
      • 2017-01-26
      • 2012-09-21
      • 1970-01-01
      • 2016-11-09
      • 1970-01-01
      • 1970-01-01
      • 2013-03-30
      相关资源
      最近更新 更多