依赖注入:从具体工厂实例化具体对象是否可以

时间:2014-02-13 18:04:49

标签: dependency-injection inversion-of-control

我对依赖注入很新,我写了一个很棒的小应用程序,就像Mark Seemann告诉我的那样,世界很棒。我甚至添加了一些额外的复杂性,只是为了看看我是否可以使用DI处理它。我可以,快乐的日子。

然后我把它带到一个真实世界的应用程序,并花了很长时间挠挠脑袋。 Mark告诉我,我不允许使用'new'关键字来实例化对象,我应该让IoC为我做这件事。

然而,说我有一个存储库,我希望它能够返回一个列表,因此:

public interface IThingRepository
{
 public IEnumerable<IThing> GetThings();
}

当然至少有一个这个接口的实现必须实例化一些东西?而且,允许ThingRepository创建一些事物似乎并不是很糟糕,因为无论如何它们都是相关的。

我可以改为绕过POCO,但在某些时候我将不得不将POCO转换为业务对象,这需要我新的东西。

这种情况似乎每当我想要一些组合根中无法知道的事情时就会出现(即我们稍后才会发现这些信息 - 例如在查询数据库时)。

有谁知道在这种情况下最佳做法是什么?

3 个答案:

答案 0 :(得分:1)

  
    

Mark告诉我,我不允许使用'new'关键字来实例化对象

  

这不是马克·西曼告诉你的,或者他的意思。您必须在一侧明确区分服务(由组合根控制)和另一侧的基元,实体,DTO,视图模型和消息。服务是injectables and all other types are newables。您应该只阻止在服务类型上使用new。例如,防止新增字符串会很愚蠢。

由于在您的示例中该服务是repository,因此假设存储库返回域对象似乎是合理的。域对象是新手,没有理由不手动new

答案 1 :(得分:1)

除了Steven的回答之外,我认为特定工厂可以新建它为其创建的特定匹配实现。

更新

另外,请检查this answer,特别是评论,其中说明了有关新增实例的内容。

示例:

public interface IContext {
    T GetById<T>(int id);
}

public interface IContextFactory {
    IContext Create();
}

public class EntityContext : DbContext, IContext {
    public T GetById<T>(int id) {
        var entity = ...;   // Retrieve from db
        return entity;
    }
}

public class EntityContextFactory : IContextFactory {
    public IContext Create() {
        // I think this is ok, since the factory was specifically created
        // to return the matching implementation of IContext.
        return new EntityContext(); 
    }
}

答案 2 :(得分:0)

感谢大家的回答,他们引导我得出以下结论。

Mark在我正在阅读的书中区分了稳定和不稳定的依赖关系(“.NET中的依赖注入”)。可以随意创建稳定的依赖项(例如字符串)。应该将不稳定的依赖项移到接缝/接口后面。

依赖是指与我们正在编写的汇编不同的汇编。

不稳定依赖项是以下任何一种

  • 它需要设置运行时环境,例如数据库,Web服务器,甚至文件系统(否则它将不可扩展或可测试,这意味着如果我们想要的话,我们无法进行后期绑定to)
  • 它还不存在(否则我们不能做并行开发)
  • 它需要未在所有机器上安装的东西(否则会导致测试困难)
  • 它包含非确定性行为(否则无法很好地测试)

所以这一切都很好。

但是,我经常在同一个装配体中隐藏接缝背后的东西。我发现这对测试非常有帮助。例如,如果我正在进行复杂的计算,则无法一次性测试整个计算 。如果我将计算分成许多较小的类并隐藏在接缝后面,那么我可以轻松地将任何arbirtary中间结果注入计算类。

所以,有了一个好老的想法,这些是我的结论:

  • 创建稳定的依赖
  • 总是可以的
  • 您永远不应该直接创建不稳定的依赖项
  • 在装配体中使用接缝可能很有用,特别是打破大类并使它们更容易测试。

在回答我原来的问题时,可以从混凝土工厂中实例化具体物体。