依赖注入 - 几个类方法中需要的新实例

时间:2011-01-10 15:22:20

标签: c# dependency-injection inversion-of-control

我有一些看起来像这样的代码:

public MyService(IDependency dependency)
{
    _dependency = dependency;
}

public Message Method1()
{
    _dependency.DoSomething();

}

public Message Method2()
{
    _dependency.DoSomething();  
}

public Message Method2()
{
    _dependency.DoSomething();  
}

现在我刚刚意识到因为依赖对象包含内部状态信息。我需要在每个方法调用中新建一个新实例

那么最好的方法是什么,仍然没有新的具体实例?

您是否会使用IoC容器并在每个方法中调用容器?或者有一种更流畅的方式,你只能打电话给容器吗?

如果我没有使用IoC容器怎么办?是否有办法不在每个方法中新建一个具体实例?

5 个答案:

答案 0 :(得分:37)

到目前为止,大多数答案都建议您将注入的依赖关系类型更改为某种Abstract Factory(一个Func<T>也是一个抽象工厂)来解决该问题。但是,如果你这样做,那将是一个漏洞抽象,因为你会让特定实现的知识决定消费者的设计。这违反了Liskov Substitution Principle

更好的选择是将MyService保持为,然后为IDependency创建一个解决特定生命周期问题的包装器:

public class TransientDependencyWrapper : IDependency
{
    public void DoSomething()
    {
        new MyStatefulDependency().DoSomething();
    }
}

将其注入MyService,而不是直接注入原始实现(MyStatefulDependency)。

如果要抽象出依赖项的创建,可以始终在此级别注入抽象工厂。

答案 1 :(得分:9)

听起来你应该注射供应商/工厂。你如何表示这取决于你(以及你的IoC支持) - 它可以简单如下:

public MyService(Func<IDependency> dependencyProvider)
{
    this.dependencyProvider = dependencyProvider;
}

public Message Method1()
{
    IDependency dependency = dependencyProvider();
    dependency.DoSomething();    
}

...或者您可以为此特定工厂类型或通用IFactory<T>等设置接口。有各种可能性 - 但核心位是您注入你需要什么,在这种情况下是“在每次通话中创建IDependency的新实现的方式”。

答案 2 :(得分:5)

如果你需要创建一个注入类型的多个实例,你应该注入IDependencyFactory而不是负责控制实例生命周期:

interface IDependencyFactory
{
    IDependency GetInstance();
}

答案 3 :(得分:3)

你可以这样做:

private readonly Func<IDependancy> _dependancy;
public MyService(Func<IDependancy> dependancy)
{
    _dependancy = dependancy;
}

public Message Method1()
{
    _dependancy().DoSomething();
}

public Message Method2()
{
    _dependancy().DoSomething();  
}

public Message Method3()
{
    _dependancy().DoSomething();  
}

然后:

var service = new MyService(() => new SomeConcreteDependency());
service.Method1();
service.Method2();
service.Method3();

答案 4 :(得分:1)

我头脑中的前两个想法是

  1. 不要在构造函数中接受它,而是在每个方法上接受它。
  2. 不是将实例传递给构造函数,而是传入工厂或每次调用func时都会创建新实例的Func<IDependency>