Dependency injection 是否应将列表成员注入域模型?
最近,我把我的努力投入到学习和理解DI上。现在我的英语越来越流利了,还有一些其他的问题 是否应将列表成员注入域模型? 在Ninject的著名例子中,我看到的想法是:Dependency injection 是否应将列表成员注入域模型?,dependency-injection,domain-driven-design,domain-model,Dependency Injection,Domain Driven Design,Domain Model,最近,我把我的努力投入到学习和理解DI上。现在我的英语越来越流利了,还有一些其他的问题 是否应将列表成员注入域模型? 在Ninject的著名例子中,我看到的想法是: public class Warrior { public Warrior(IWeapon weapon) { this.weapon = weapon; } public void Attack() { weapon.Hit(); } } public Archer : Warrior { // Her
public class Warrior {
public Warrior(IWeapon weapon) { this.weapon = weapon; }
public void Attack() { weapon.Hit(); }
}
public Archer : Warrior {
// Here, the weapon would be bound to a bow.
public Archer(IWeapon weapon) : base(weapon) { }
}
public Ninja : Warrior {
// On the contrary, the weapon would here be bound to a katana.
public Ninja(IWeapon weapon) : base(weapon) { }
}
因此,根据IWeapon
被注入的内容,上下文绑定定义应该创建什么武器
我知道在我的模型中注入DAO就是实现活动记录设计模式,有些人认为这是一种反模式。其他人更喜欢POCO作为域对象,简单的数据表示,这不符合DDD的规则
回到我的担忧,我想说,Warrior
、Archer
和Ninja
都是我的领域模型的一部分
现在,如果我的模型有一个IList
而不是IWeapon
,该怎么办?DI会有用吗,还是会变得无用
public class MyClass {
public MyClass(IList<MyOtherClass> myOtherClasses) {
MyOtherClassesA = myOtherClasses.OfType<MyOtherClassA>().ToList();
MyOtherClassesB = myOtherClasses.OfType<MyOtherClassB>().ToList();
}
public IList<MyOtherClassA> MyOtherClassesA { get; protected set; }
public IList<MyOtherClassB> MyOtherClassesB { get; protected set; }
}
错误
public class Bug : Artifact {
public string Resolution { get; set; }
}
障碍
public abstract class Artifact {
public string Description { get; set; }
public string Title { get; set; }
}
public class Impediment : Artifact {
}
任务
public class Task : Artifact {
public float EstimatedTime { get; set; }
public float RealTime { get; set; }
}
UserStory
public class UserStory : Artifact {
public string AcceptanceCriteria { get; set; }
public int BusinessValue { get; set; }
public int Complexity { get; set; }
public IList<Impediment> Impediments { get; protected set; }
public IList<Task> Tasks { get; protected set; }
}
以及我的单元测试:
[TestFixture]
public class UserStoryTests {
[Test]
public void ImpedimentsShouldBeInitializedByDefault() {
userStory.Impediments.Should().NotBeNull().And.BeOfType<IList<Impediment>>();
}
public void TasksShouldBeInitializedByDefault() {
userStory.Tasks.Should().NotBeNull().And.BeOfType<IList<Task>>();
}
[TestFixtureSetUp]
public void UserStorySetUp() {
impediments = new Mock<IList<Impediment>>();
tasks = new Mock<IList<Task>>();
userStory = new UserStory(impediments.Object, tasks.Object);
}
private Mock<IList<Impediment>> impediments;
private Mock<IList<Task>> tasks;
private UserStory userStory;
}
[TestFixture]
公共类UserStoryTests{
[测试]
公共无效障碍应默认初始化(){
userStory.industries.Should().NotBeNull()和.BeOfType();
}
公共无效任务应默认初始化(){
userStory.Tasks.Should().NotBeNull()和.BeOfType();
}
[TestFixtureSetUp]
public void UserStorySetUp(){
障碍=新模拟();
任务=新建模拟();
userStory=newuserstory(障碍物.Object,任务.Object);
}
私人模拟障碍;
私人模拟任务;
私人用户故事;
}
问题来自于Sprint
。Sprint
需要四个列表,我发现为了清晰易读而注入的对象太多了。如果我没有弄错的话,有人说一个依赖性太多的类可能会破坏规则。虽然即使使用Sprint
类,我也没有打破SRP
,但是我对注入四个不同的列表感到非常不舒服。我想我可以使用多态性来注入一个包含它们的列表,因为毕竟它们基本上都是Artifact
s
<强>也许我应该简单地考虑使用<代码>抽象工厂[/COD>模式],这样我的四个列表就如预期的那样得到适当的初始化,而我只需要注入一个单一的工厂类,单一的责任包括创建列表?< /强>
< P>我想你误解了一点。它不涉及不同的战士类,它们与IWeapon
的特定子类型相关联。只有一个武士
,他可以使用任何类型的IWeapon
。因此,一名只能使用特定武器的弓箭手不在考虑之列,也不适合。相反,只需将弓
注入武士
我完全可以。一些DI容器甚至允许自动关联列表。也就是说,您可以告诉容器以列表的形式注入在给定程序集中找到的接口的所有实现
但是,只有当您可以以相同的方式对待所有成员时,这才真正起作用,也就是说,您不必按子类型进行区分。如果你想将战士的近战武器从他的弓集合中分离出来,最好是注入两个不同类型的列表
如果您想了解更多有关正确的DI模式的信息,我非常推荐。我不明白,这与DDD有什么关系?你能注入列表吗?当然是否应该按具体的子类型划分列表?当然不是。想象一下项目被注入的情况,它们不是您期望的子类型。或者是一个列表,它不包含您期望的子类型的任何项。您是否建议我在构造函数中使用
new
关键字初始化列表,而不使用DI?如果是这样的话,我觉得没问题。我只想知道DI不被考虑的限制是什么,否则,它不会提供任何优势。不,一定要注入它们!但不要注入一个基类型列表,然后按派生类型拆分。请留意我的编辑。检查以了解当构造函数变得太宽时,即遇到“过度注入”时该怎么办。+1感谢您的启发。我以Ninject为灵感,没有验证任何东西,只是为了树立我的想法这本书我被推荐了不止一次。几周前我终于买下了它。现在,你说服我开始阅读谢谢你的时间!无论如何,我想知道列表是否应该被注入,因为它们是模型本身的一部分,如果你以我在Scrum上的编辑为例。Sprint是由用户故事定义的,而用户故事又是由它的任务、bug、障碍以及可能的其他用户故事定义的。这是域模型的唯一定义。那么,模型如何从列表注入中获益呢?我希望马克·西曼的书能回答这样的问题=P
[TestFixture]
public class UserStoryTests {
[Test]
public void ImpedimentsShouldBeInitializedByDefault() {
userStory.Impediments.Should().NotBeNull().And.BeOfType<IList<Impediment>>();
}
public void TasksShouldBeInitializedByDefault() {
userStory.Tasks.Should().NotBeNull().And.BeOfType<IList<Task>>();
}
[TestFixtureSetUp]
public void UserStorySetUp() {
impediments = new Mock<IList<Impediment>>();
tasks = new Mock<IList<Task>>();
userStory = new UserStory(impediments.Object, tasks.Object);
}
private Mock<IList<Impediment>> impediments;
private Mock<IList<Task>> tasks;
private UserStory userStory;
}