使用抽象类进行依赖注入

时间:2014-12-04 20:38:51

标签: c# dependency-injection

我在最后两天努力抓住DI。

我有两个问题:

  1. 如果我有一些共同的功能,为什么我不能用抽象类来实现DI呢?
  2. 在我的例子中,我在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();
        }
    }
    

1 个答案:

答案 0 :(得分:3)

关于你的第一点:

假设您要测试使用抽象类的内容。如果您直接使用抽象类,那么如果您想在公共类的共享功能中执行不同的操作,那么您无能为力。

使用接口,您已经破坏了与依赖关系的耦合。这就是Dependency Inversion PrincipleSOLID所说的“高级模块不应该依赖于低级模块。两者都应该依赖于抽象”。你的类不应该依赖于低级类(即使它是一个抽象类)来完成它的工作。低级和高级类都应该依赖于定义它们如何交互的接口。使用界面有助于将两者分开,为您提供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的接口的多个实现

我不知道StructureMap如何处理这个问题,但可能会有一些逻辑决定你何时使用Thing1Things2。您可以向StructureMap提供一个委托,它可以用来获取包含该逻辑的IThing

或者,您可以让工厂获取一些参数并决定返回哪个IThing。在某些情况下,我在我的工厂和构造函数中注入了一个接口,或者让工厂使用IThing创建对象,使用ThingFactory来获得正确的接口。