我正在写一个库,它将为它的使用者提供一个公共类型的集合。
我想让这个库中的类型对依赖注入友好。这意味着每个类都需要有一个构造函数,通过它可以指定被初始化对象的每个依赖项。我还希望这个库遵循约定优先于配置的原则。这意味着,如果消费者想要默认行为,他可以使用无参数构造函数,对象将以某种方式为自己构造依赖项。
在示例(C#)中:
public class Samurai {
private readonly IWeapon _weapon;
// consumers will use this constructor most of the time
public Samurai() {
_weapon = ??? // get an instance of the default weapon somehow
}
// consumers will use this constructor if they want to explicitly
// configure dependencies for this instance
public Samurai(IWeapon weapon) {
_weapon = weapon;
}
}我的第一个解决方案是使用服务定位器模式。
代码将如下所示:
...
public Samurai() {
_weapon = ServiceLocator.Instance.Get<IWeapon>();
}
...不过,我对此有一个问题。服务定位器已经被标记为反模式(link),我完全同意这些观点。另一方面,Martin Fowler主张在这种情况下使用服务定位器模式(库项目) (link)。我想要小心,在发现服务定位器确实是个坏主意后,消除重写库的可能。
所以总而言之,你认为服务定位器在这个场景中合适吗?我应该用一种完全不同的方式来解决我的问题吗?欢迎任何想法..。
发布于 2012-03-29 17:51:43
如果您想让不使用DI容器的用户的生活变得更轻松,您可以通过一个专用的Defaults类提供默认实例,该类具有如下方法:
public virtual Samurai CreateDefaultSamurai()
{
return new Samurai(CreateDefaultWeapon());
}
public virtual IWeapon CreateDefaultWeapon()
{
return new Shuriken();
}这样,您就不需要用默认构造函数污染类本身,您的用户也不会有无意中使用这些默认构造函数的风险。
发布于 2012-03-29 07:19:21
还有一种选择,那就是注入一个特定的提供者,假设你的案例中有一个WeaponProvider到你的类中,这样它就可以为你做查找:
public interface IWeaponProvider
{
IWeapon GetWeapon();
}
public class Samurai
{
private readonly IWeapon _weapon;
public Samurai(IWeaponProvider provider)
{
_weapon = provider.GetWeapon();
}
}现在,您可以为武器提供本地默认提供程序:
public class DefaultWeaponProvider : IWeaponProvider
{
public IWeapon GetWeapon()
{
return new Sword();
}
}由于这是一个本地默认值(而不是来自不同程序集的默认值,所以它不是“杂种注入”),您也可以将其用作您的武士类的一部分:
public class Samurai
{
private readonly IWeapon _weapon;
public Samurai() : this(new DefaultWeaponProvider())
{
}
public Samurai(IWeaponProvider provider)
{
_weapon = provider.GetWeapon();
}
}发布于 2014-06-13 00:50:45
我在我的C#项目中使用了以下方法。我们的目标是实现依赖注入(用于单元/模拟测试),同时不会破坏“正常用例”的代码实现(即拥有大量通过执行流级联的new())。
public sealed class QueueProcessor : IQueueProcessor
{
private IVbfInventory vbfInventory;
private IVbfRetryList vbfRetryList;
public QueueProcessor(IVbfInventory vbfInventory = null, IVbfRetryList vbfRetryList = null)
{
this.vbfInventory = vbfInventory ?? new VbfInventory();
this.vbfRetryList = vbfRetryList ?? new VbfRetryList();
}
}这允许依赖注入,但也意味着任何消费者都不必担心“默认实例流”应该是什么。
https://stackoverflow.com/questions/9915472
复制相似问题