Wcf DI-过度使用还是糟糕的设计?
有两种情况下,队友们对如何使用DI不一致Wcf DI-过度使用还是糟糕的设计?,wcf,dependency-injection,Wcf,Dependency Injection,有两种情况下,队友们对如何使用DI不一致 我需要一个新的循环实例。我无法将作业实例传递给类ctor for(var item in items){ var job = new Job(); job.execute(item) } 一个选项是将IContainer注入类并使用container.Resolve()。但这是反模式的,容器是暴露的。另一个选项是注入工厂并将容器注入工厂。工厂方法最终将使用container.Resolve()这略有不同,但container仍然是公开的,并
for(var item in items){
var job = new Job();
job.execute(item)
}
一个选项是将IContainer
注入类并使用container.Resolve()
。但这是反模式的,容器是暴露的。另一个选项是注入工厂并将容器注入工厂。工厂方法最终将使用container.Resolve()
这略有不同,但container仍然是公开的,并且是反模式的和构造
DefaultPaymentOption
注入Order
实例。如果我将DefaultPaymentOption
类注入Order
,我就失去了DTO的简单性,它也违反了DB数据<草稿模式下的订单不需要代码>默认付款选项。我们做得太过分了吗?在我的理解中,DI应该用于对象从外部世界执行一些操作,而不是用于合成在我看来,
new
关键字没有错。它是语言的一部分,所以它可以被使用,但与其他一切一样,你必须明智地使用它。DI的发明是为了使代码更易于测试、模块化和维护
如果您的示例中的job
没有需要容器(存储库、服务等)的依赖项,是可测试的,并且不会给您的依赖项引入新的周期,那么,imho,new
完全可以。如果将来您需要容器中的依赖项,那么您将用container.get(…)
替换new
。和DTO一样,从容器中获取它们是一种过分的做法,因为它们应该没有逻辑和依赖关系
而且你不必公开你的课程。1) 有些语言提供的可视范围比公共和私有范围更大(例如java—默认范围)。2) 您不必单独测试每个类——这称为单元测试,而不是类测试。但可悲的事实是:有时为了更简单的测试,您必须放松可见性我看到您的DI方法的一个指导问题来自于对它的用途的误解。当您试图将系统的实现细节抽象为通过单元测试单独测试的小类时,您希望使用DI。如果您创建了一个包含内部类的具体类,那么很可能您的类做了太多的工作,应该分解为经过单元测试的组成部分。这样,当某个代码出现故障时,您几乎可以立即知道问题出在哪里,这取决于代码的哪一部分出现故障 我会更深入地阅读坚实的设计原则和单元测试,以更坚实地理解这些模式背后的目的
public interface ISomeObject
{
void DoSomething();
}
public interface ISomeConfigurationDependency
{
// A dependency that is configured in the DI container.
}
public interface ISomeRuntimeDependency
{
// A dependency created by some other factory at runtime.
}
public interface ISomeObjectFactory
{
ISomeObject Create(string someRuntimeValue, ISomeRuntimeDependency someRuntimeDependency);
void Release(ISomeObject someObject);
}
public class SomeObject : ISomeObject
{
private readonly string someRuntimeValue;
private readonly string someConfigurationValue;
private readonly ISomeRuntimeDependency someRuntimeDependency;
private readonly ISomeConfigurationDependency someConfigurationDependency;
public SomeObject(
string someRuntimeValue,
string someConfigurationValue,
ISomeRuntimeDependency someRuntimeDependency,
ISomeConfigurationDependency someConfigurationDependency)
{
if (string.IsNullOrEmpty(someRuntimeValue))
throw new ArgumentNullException("someRuntimeValue");
if (string.IsNullOrEmpty(someConfigurationValue))
throw new ArgumentNullException("someConfigurationValue");
if (someRuntimeDependency == null)
throw new ArgumentNullException("someRuntimeDependency");
if (someConfigurationDependency == null)
throw new ArgumentNullException("someConfigurationDependency");
this.someRuntimeValue = someRuntimeValue;
this.someConfigurationValue = someConfigurationValue;
this.someRuntimeDependency = someRuntimeDependency;
this.someConfigurationDependency = someConfigurationDependency;
}
public void DoSomething()
{
Console.WriteLine("I am using the dependencies now");
}
}
public class SomeObjectFactory : ISomeObjectFactory
{
private readonly string someConfigurationValue;
private readonly ISomeConfigurationDependency someConfigurationDependency;
public SomeObjectFactory(string someConfigurationValue, ISomeConfigurationDependency someConfigurationDependency)
{
if (string.IsNullOrEmpty(someConfigurationValue))
throw new ArgumentNullException("someConfigurationValue");
if (someConfigurationDependency == null)
throw new ArgumentNullException("someConfigurationDependency");
this.someConfigurationValue = someConfigurationValue;
this.someConfigurationDependency = someConfigurationDependency;
}
public ISomeObject Create(string someRuntimeValue, ISomeRuntimeDependency someRuntimeDependency)
{
if (string.IsNullOrEmpty(someRuntimeValue))
throw new ArgumentNullException("someRuntimeValue");
if (someRuntimeDependency == null)
throw new ArgumentNullException("someRuntimeDependency");
// The only thing a factory does is new up an instance -
// no business logic here. There is nothing to test
// here because nothing can go wrong.
return new SomeObject(
someRuntimeValue,
this.someConfigurationValue,
someRuntimeDependency,
this.someConfigurationDependency);
}
// Use release if you want to expose the factory as a formal extension point
// that might have unmanaged dependencies.
public void Release(ISomeObject someObject)
{
var disposable = someObject as IDisposable;
if (disposable != null)
disposable.Dispose();
}
}
public class SomeService : ISomeService
{
private readonly ISomeObjectFactory someObjectFactory;
private readonly ISomeRuntimeDependencyFactory someRuntimeDependencyFactory;
public SomeService(ISomeObjectFactory someObjectFactory, ISomeRuntimeDependencyFactory someRuntimeDependencyFactory)
{
if (someObjectFactory == null)
throw new ArgumentNullException("someObjectFactory");
if (someRuntimeDependencyFactory == null)
throw new ArgumentNullException("someRuntimeDependencyFactory");
this.someObjectFactory = someObjectFactory;
this.someRuntimeDependencyFactory = someRuntimeDependencyFactory;
}
public void Run()
{
// Setup runtime variables
var someRuntimeValue = "test";
var someRuntimeDependency = this.someRuntimeDependencyFactory.Create();
// Get a runtime instance
var someObject = this.someObjectFactory.Create(someRuntimeValue, someRuntimeDependency);
try
{
someObject.DoSomething();
}
finally
{
this.someObjectFactory.Release(someObject);
}
}
}