我有一些看起来像这样的代码:
public MyService(IDependency dependency)
{
_dependency = dependency;
}
public Message Method1()
{
_dependency.DoSomething();
}
public Message Method2()
{
_dependency.DoSomething();
}
public Message Method2()
{
_dependency.DoSomething();
}
现在我刚刚意识到因为依赖对象包含内部状态信息。我需要在每个方法调用中新建一个新实例
那么最好的方法是什么,仍然没有新的具体实例?
您是否会使用IoC容器并在每个方法中调用容器?或者有一种更流畅的方式,你只能打电话给容器吗?
如果我没有使用IoC容器怎么办?是否有办法不在每个方法中新建一个具体实例?
答案 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)
我头脑中的前两个想法是
Func<IDependency>
。