【问题标题】:Autofac: long-lived objects requiring short-lived objects during single method callsAutofac:在单个方法调用期间需要短期对象的长期对象
【发布时间】:2013-04-15 18:38:24
【问题描述】:

我有一个 X 类,我在 Autofac 中注册为单实例,因为创建它的成本相当高。

X 有一个方法DoSomething 执行一些操作。但是,要在DoSomething 中完成其任务,X 需要额外的依赖项。通常,我会将它们注入构造函数中,但在这种情况下,这会变得很困难,因为依赖项绑定到更窄的范围,例如每个 httprequest 的实例或每个生命周期的实例。我不能使用Func<T>,因为这仍然会解析委托被实例化的生命周期中的对象,所以我没有任何收获。

下一个选项是将依赖项作为参数传递给DoSomething,但是存在依赖项的事实实际上只是一个实现细节。事实上,我通过一个接口访问 X。我宁愿不要通过添加这个参数来导致泄漏抽象。

当然,在方法中手动解决依赖关系(即服务定位器样式)也不是很好。即便如此,我也有一个问题是我不确定如何访问正确的IComponentContext。该类可以用在 Web 应用程序或常规应用程序中,或在 Web 应用程序的线程中,但在任何请求之外。如何确定“当前”生命周期范围?

所以基本问题是这样的:

class X : ISomething 
{
  public void DoSomething()
  {
    IDependency dependency = ?;
    dependency.UseMe();
    /* more stuff */
  }
}

理想情况下,我希望能够向构造函数中注入一些东西,以便稍后允许我解析当前生命周期范围内的实际对象,如下所示:

class X : ISomething 
{
  IResolveLater<IDependency> dependencyResolver;

  public X(IResolveLater<IDependency> dependencyResolver){
    this.dependencyResolver = dependencyResolver;
  }

  public void DoSomething()
  {
    IDependency dependency = dependency.Resolve();
    dependency.UseMe();
    /* more stuff */
  }
}

我当然在这里闻到了设计问题,但我无法真正指出它。我该如何解决这个一般性问题:一个长期存在的对象,它需要本地范围内的短期对象来进行单个操作。我通常更喜欢不同的顺序:短期对象取决于长期对象。

我也在考虑以某种方式将长期存在的东西从 X 中移出,并创建一个额外的短期类 XHelper 充当某种“适配器”:

class X 
{

  void DoSomething(IDependency dependency)
  {
    /* do something */
  }
}

class XHelper : ISomething
{
  X x;
  public XHelper(X x, IDependency dependency)
  {
    this.x = x;
    this.dependency = dependency;
  }

  public void DoSomething()
  {
    x.DoSomething(dependency);
  }
}

因此,当我需要 ISomething 时,我会根据需要解析 XHelper(而不是 X),它会自动注入适当的依赖项。我需要为此引入一个额外的类型,这有点麻烦。

我怎样才能以最优雅的方式解决这种情况?

【问题讨论】:

  • 我的第一个想法是,当两个对象的生命周期差异如此之大,同时IDependency的个体实例如此有影响力和重要性时,也许应该有一个抽象这实际上反映了这种关系。除此之外,IResolveLater 实例从哪里获取依赖实例,以便单独调用 DoSomething()
  • @GCATNM 您愿意详细说明“实际反映这种关系的抽象”部分吗?我认为XHelper 类(忽略命名)可能是这种抽象。回复IResolveLater:它会以某种方式自动从“当前”生命周期范围内解析实例。虽然我不确定如何定义“当前”的语义。例如,它可能是当前打开的最内层(= 最深嵌套的)生命周期范围。但我不确定这是否有意义。目前,我认为XHelper 方法是可行的方法。
  • 最简单的方法是使用Func&lt;Owned&lt;IDependency&gt;&gt;

标签: dependency-injection ioc-container autofac


【解决方案1】:

在我看来,您的用例实际上是一个伪装的简单工厂模式。

创建一个简单的 DependencyFactory,它有一个 Create() 方法,该方法返回您想要实现 IDependency 的任何具体类的实例,然后让您的 DependencyFactory 实现一个接口 IDependencyFactory。

向容器注册IDependencyFactory,修改Class X的构造函数,取一个IDependencyFactory。

使用 IDependencyFactory 实例在您的方法 DoSomething() 中解析 IDependency 的具体实例并在其上调用 DoSomething()。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-17
    • 1970-01-01
    • 2021-11-08
    相关资源
    最近更新 更多