为什么不使用 IoC 容器来解析实体/业务对象的依赖关系?

我理解 DI 背后的概念,但我只是在学习不同的 IoC 容器可以做什么。似乎大多数人都提倡使用 IoC 容器来连接无状态服务,但是如何将它们用于实体等有状态对象呢?

不管它是对是错,我通常用行为填充我的实体,即使这种行为需要一个外部类。例如:

public class Order : IOrder
{


private string _ShipAddress;
private IShipQuoter _ShipQuoter;


public Order(IOrderData OrderData, IShipQuoter ShipQuoter)
{
// OrderData comes from a repository and has the data needed
// to construct order
_ShipAddress = OrderData.ShipAddress;  // etc.
_ShipQuoter = ShipQuoter;


}


private decimal GetShippingRate()
{
return _ShipQuoter.GetRate(this);
}
}

如您所见,依赖项是构造函数注入的。

  1. 让您的实体依赖于诸如 ShipQuoter 之类的外部类是否被认为是不好的做法?如果我正确理解了这个定义,那么消除这些依赖性似乎将我引向一个贫血领域。

  2. 使用 IoC 容器来解决这些依赖关系并在需要时构造一个实体是不是一个坏习惯?有可能做到吗?

谢谢你的建议。

11182 次浏览

The first question is the most difficult to answer. Is it bad practice to have Entities depend on outside classes? It's certainly not the most common thing to do.

If, for example, you inject a Repository into your Entities you effectively have an implementation of the Active Record pattern. Some people like this pattern for the convenience it provides, while others (like me) consider it a code smell or anti-pattern because it violates the Single Responsibility Principle (SRP).

You could argue that injecting other dependencies into Entities would pull you in the same direction (away from SRP). On the other hand you are certainly correct that if you don't do this, the pull is towards an Anemic Domain Model.

I struggled with all of this for a long time until I came across Greg Young's (abandonded) paper on DDDD where he explains why the stereotypical n-tier/n-layer architecture will always be CRUDy (and thus rather anemic).

Moving our focus to modeling Domain objects as Commands and Events instead of Nouns seems to enable us to build a proper object-oriented domain model.

The second question is easier to answer. You can always use an Abstract Factory to create instances at run-time. With Castle Windsor you can even use the Typed Factory Facility, relieving you of the burden of implementing the factories manually.

I know this is an old post but wanted to add. The domain entity should not persist itself even if you pass in an abstracted repository in ctor. The reason I am suggestion this is not merely that it violates SRP, it also contrary to DDD's aggregation. Let me explain, DDD is suited for complex apps with inherently deep graphs, therefore, we use aggregate or composite roots to persist changes to the underlying "children", so when we inject persistence into the individual children we violate the relationship children have to the composite or aggregate root that should be "in charge" of the life cycle or aggregation. Of course the composite root or aggregate does not persist it's own graph either. Another is with injecting dependencies of DDD objects is that an injected domain object effectively has no state until some other event takes place to hydrate its state. ANy consumer of the code will be forced to init or setup the domain object first before they can invoke business behavior which violates encapsulation.