Autofac:在单个方法调用期间需要短期对象的长寿命对象

时间:2013-04-15 18:38:25

标签: dependency-injection ioc-container autofac

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

X有一个方法DoSomething可以执行某些操作。但是,要在DoSomething中执行其任务,X需要其他依赖项。通常,我会在构造函数中注入它们,但在这种情况下,这会变得很困难,因为依赖性受限于较窄的范围,例如instance-per-httprequest或instance-per-lifetime-scope。我不能使用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),它会自动获取注入的正确依赖项。我需要为此引入一个额外的类型,这有点麻烦。

如何以最优雅的方式解决这种情况?

1 个答案:

答案 0 :(得分:0)

听起来我的用例实际上是伪装的简单工厂模式。

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

将IDependencyFactory注册到容器中,并修改Class X的构造函数以获取IDependencyFactory。

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