我在最后两天努力抓住DI。
我有两个问题:
在我的例子中,我在writefile下创建了很多类实例,所以我应该从那里移出所有对象吗?如果我有分层设计怎么办?这些课程应该一直通过吗?
public interface IWriteFile
{
void write();
}
public class WriteXMLFile : IWriteFile
{
public void write()
{
}
}
public class writefile
{
IWriteFile _file;
public writefile(IWriteFile file)
{
_file = file;
}
public void WriteMyFile()
{
_file.write();
}
}
答案 0 :(得分:3)
假设您要测试使用抽象类的内容。如果您直接使用抽象类,那么如果您想在公共类的共享功能中执行不同的操作,那么您无能为力。
使用接口,您已经破坏了与依赖关系的耦合。这就是Dependency Inversion Principle中SOLID所说的“高级模块不应该依赖于低级模块。两者都应该依赖于抽象”。你的类不应该依赖于低级类(即使它是一个抽象类)来完成它的工作。低级和高级类都应该依赖于定义它们如何交互的接口。使用界面有助于将两者分开,为您提供loose coupling。还有其他东西可以处理它们。
强大的DI框架实际上为您处理了很多这种复杂性。
假设您有一个类 - Thing
- 它有很多依赖项。
public Thing(
IThingRepository repository,
IEmailer emailer,
ILogger logger,
INeedMoreStuff stuff
) : IThing
设置IoC容器时,您需要执行以下操作以关联每个接口使用的实现:
IoC.Register<MySqlThingRepository>().As<IThingRepository>();
IoC.Register<MicrosoftExchangeEmailer>().As<IEmailer>();
IoC.Register<TruncatingFileLogger>().As<ILogger>();
IoC.Register<MoreStuff>().As<INeedMoreStuff>();
IoC.Register<Thing>().As<IThing>();
然后你就可以做到:
IThing thing = IoC.Resolve<IThing>();
这些花哨的框架可以处理所有依赖项(因为你告诉它如何获取它们)并为你构建一个Thing
。
话虽这么说,有时像这样的花哨框架是矫枉过正的。在这些情况下,我通常使用factory pattern来抽象出创建对象的细节,同时仍然确保正在创建的对象遵循良好的DI原则,如构造函数注入其依赖项。
某人described多态性只是“相同的接口,不同的实现。可替代性”。 Wikipedia将其定义为“为不同类型的实体提供单一接口”。根据这些定义,我认为使用接口不会违背多态性。我觉得C#接口通常足以提供相同“接口”的不同实现。
是的,您可以使用抽象基类来执行相同的操作,但我仅使用它,如果有一组共同的功能,我可以将其分解到基类中以保持我的代码DRY。
我不知道StructureMap如何处理这个问题,但可能会有一些逻辑决定你何时使用Thing1
与Things2
。您可以向StructureMap提供一个委托,它可以用来获取包含该逻辑的IThing
。
或者,您可以让工厂获取一些参数并决定返回哪个IThing
。在某些情况下,我在我的工厂和构造函数中注入了一个接口,或者让工厂使用IThing
创建对象,使用ThingFactory
来获得正确的接口。