首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >库项目中构造函数参数的默认值

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

Stack Overflow用户
提问于 2012-03-29 04:52:00
回答 3查看 1.8K关注 0票数 7

我正在写一个库,它将为它的使用者提供一个公共类型的集合。

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

在示例(C#)中:

代码语言:javascript
复制
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;
    }
}

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

代码将如下所示:

代码语言:javascript
复制
...
public Samurai() {
    _weapon = ServiceLocator.Instance.Get<IWeapon>();
}
...

不过,我对此有一个问题。服务定位器已经被标记为反模式(link),我完全同意这些观点。另一方面,Martin Fowler主张在这种情况下使用服务定位器模式(库项目) (link)。我想要小心,在发现服务定位器确实是个坏主意后,消除重写库的可能。

所以总而言之,你认为服务定位器在这个场景中合适吗?我应该用一种完全不同的方式来解决我的问题吗?欢迎任何想法..。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-03-29 17:51:43

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

代码语言:javascript
复制
public virtual Samurai CreateDefaultSamurai()
{
   return new Samurai(CreateDefaultWeapon());
}

public virtual IWeapon CreateDefaultWeapon()
{
   return new Shuriken();
}

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

票数 4
EN

Stack Overflow用户

发布于 2012-03-29 07:19:21

还有一种选择,那就是注入一个特定的提供者,假设你的案例中有一个WeaponProvider到你的类中,这样它就可以为你做查找:

代码语言:javascript
复制
public interface IWeaponProvider
{
    IWeapon GetWeapon();
}

public class Samurai
{
    private readonly IWeapon _weapon;

    public Samurai(IWeaponProvider provider)
    {
        _weapon = provider.GetWeapon();
    }
}

现在,您可以为武器提供本地默认提供程序:

代码语言:javascript
复制
public class DefaultWeaponProvider : IWeaponProvider
{
    public IWeapon GetWeapon()
    {
        return new Sword();
    }
}

由于这是一个本地默认值(而不是来自不同程序集的默认值,所以它不是“杂种注入”),您也可以将其用作您的武士类的一部分:

代码语言:javascript
复制
public class Samurai
{
    private readonly IWeapon _weapon;

    public Samurai() : this(new DefaultWeaponProvider())
    {
    }

    public Samurai(IWeaponProvider provider)
    {
        _weapon = provider.GetWeapon();
    }
}
票数 1
EN

Stack Overflow用户

发布于 2014-06-13 00:50:45

我在我的C#项目中使用了以下方法。我们的目标是实现依赖注入(用于单元/模拟测试),同时不会破坏“正常用例”的代码实现(即拥有大量通过执行流级联的new())。

代码语言:javascript
复制
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();
    }
}

这允许依赖注入,但也意味着任何消费者都不必担心“默认实例流”应该是什么。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9915472

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档