库项目中构造函数参数的默认值

Tom*_*mas 6 dependency-injection inversion-of-control default-value service-locator

我正在编写一个库,为其消费者提供一系列公共类型.

我想从这个库依赖注入友好的类型.这意味着每个类都需要一个构造函数,通过该构造函数可以指定要初始化的对象的每个依赖项.我还希望库遵循约定优于配置原则.这意味着如果消费者想要默认行为,他可以使用无参数构造函数,并且该对象将以某种方式为自己构造依赖关系.

在示例(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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我的第一个解决方案是使用服务定位器模式.

代码如下所示:

...
public Samurai() {
    _weapon = ServiceLocator.Instance.Get<IWeapon>();
}
...
Run Code Online (Sandbox Code Playgroud)

不过,我对此有疑问.服务定位器已被标记为反模式(链接),我完全同意这些参数.另一方面,Martin Fowler主张在这种情况下准确使用服务定位器模式(库项目)(链接).我想要小心并消除在显示服务定位器确实是个坏主意后重写库的可能性.

总而言之 - 您认为服务定位器在这种情况下是否正常?我应该以完全不同的方式解决我的问题吗?欢迎任何想法......

Wim*_*nen 4

如果您想让不使用 DI 容器的用户的生活更轻松,您可以通过专用类提供默认实例,Defaults该类具有如下方法:

public virtual Samurai CreateDefaultSamurai()
{
   return new Samurai(CreateDefaultWeapon());
}

public virtual IWeapon CreateDefaultWeapon()
{
   return new Shuriken();
}
Run Code Online (Sandbox Code Playgroud)

这样,您就不需要使用默认构造函数来污染类本身,并且您的用户也不会面临无意中使用这些默认构造函数的风险。

  • 保持类 DI 友好很重要。+1 (2认同)