C# 依赖注入和显式接口实现

C# 依赖注入和显式接口实现,c#,dependency-injection,explicit-interface,C#,Dependency Injection,Explicit Interface,在依赖注入方面显式实现接口是否有好处 据我所知,接口可以显式或隐式实现: interface IFoo { void Bar(); } //implicit implementation class Foo1 : IFoo { public void Bar(){} } //explicit implementation class Foo2 : IFoo { void IFoo.Bar(){} } 现在,显式实现只能通过调用接口方法来调用,而隐式实现可以直接在类的

在依赖注入方面显式实现接口是否有好处

据我所知,接口可以显式或隐式实现:

interface IFoo
{
    void Bar();
}

//implicit implementation
class Foo1 : IFoo
{
    public void Bar(){}
}

//explicit implementation
class Foo2 : IFoo
{
    void IFoo.Bar(){}
}
现在,显式实现只能通过调用接口方法来调用,而隐式实现可以直接在类的实例上调用:

class Baz
{
    void Ba()
    {
        Foo1 foo1 = new Foo1();
        foo1.Bar();

        Foo2 foo2 = new Foo2();
        foo2.Bar();    //syntax error

        IFoo foo2_explicit = new Foo2();
        foo2_explicit.Bar();
    }
}
因此,使用显式接口实现,不能意外地调用具体类上的方法,但必须调用接口方法。这是防止紧密耦合的代码,因为这是DI的一个目的,还是我在这里找错了方向?毕竟,不能意外地编写一个构造函数或方法来注入一个具体的类而不是一个接口:

class Baz
{
    void Ba(Foo2 foo)
    {
        foo.Bar(); //syntax error
    }

    void Bb(IFoo foo)
    {
        foo.Bar();
    }
}

若您的类在容器中,那个么您可以使用接口。因此,没有任何好处

但是,如果直接使用类(例如在测试中),则必须强制转换才能访问该方法,这并不方便


总计:当您在容器中使用类时,优势为0,对测试不利。

通常,依赖项注入的目的是解耦,您可以通过将抽象注入其客户端来实现:

public class Baz
{
    private readonly IFoo foo;

    public Baz(IFoo foo)
    {
        this.foo = foo;
    }

    // Members using this.foo go here...
}
这确保了
Baz
依赖于
IFoo
,并且与任何具体实现解耦

具体类是否隐式或显式地实现
IFoo
,没有区别


偶尔,一个类可能会有一个错误,但这并不特别正常;当它发生时,具体的依赖关系是具体的,因此通常根本不会实现接口。在这种情况下,显式和隐式接口实现是不相关的。

在我看来,一般来说,应该始终保留对类型“刚好足够”使用的对象的引用。考虑下面的例子:

public interface IDo
{
    void Do();
}

public interface IWatch
{
    void Watch();
}

public class Foo : IDo, IWatch
{
    public void Dummy() { }

    public void Watch() { }

    public void Do() { }
}
然后:

//I only want to use Do()
IDo aFoo = new Foo();

//I only want to use Watch()
IWatch bFoo = new Foo();

//I want to use stuff from Foo and optionally stuff from IDo or IWatch
Foo cFoo = new Foo();
当涉及到使用依赖注入容器(如MEF或Unity)时,您应该使用接口将对象导出到容器中,并使用相同的接口类型导入它


遵循这些模式,我并不认为使用显式接口实现有什么好处。(这也使得在文本编辑器上方的标准Visual Studio组合框中查找实现方法变得更加困难)

能否更新代码以使用IFoo而不是Foo?在我看来,这让人困惑……完成了——对不起,通常我尊重代码约定……这就是我想要达到的目的。如果出于某种模糊的原因,人们没有注意到并编写了一个需要具体类的构造函数:
publicbaz(foo1foo)
,那么使用显式接口实现将禁止对对象方法的任何调用。试图将一个具体的实现转换为它的接口会敲响一些警钟,不是吗?如果您意外地添加了一个需要具体类的构造函数,那么您就失去了依赖注入的解耦功能。这是服务的一个更大的问题,应该从根本上解决,而不是由任意的客户端修补。