9

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

据我了解,接口可以显式或隐式实现:

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();
    }
}
4

3 回答 3

8

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

public class Baz
{
    private readonly IFoo foo;

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

    // Members using this.foo go here...
}

这确保了Baz依赖于IFoo,并且与任何具体实现解耦

具体类是IFoo隐式实现还是显式实现都没有区别。

偶尔,一个类可能有一个具体的依赖,但这不是特别正常;当它发生时,具体的依赖是具体的,所以通常根本不会实现接口。在这种情况下,显式与隐式接口实现无关。

于 2015-07-28T11:36:11.617 回答
1

如果您的类在容器中,那么您使用接口。所以,没有任何好处。

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

总计:当您在容器中使用类并且对测试不利时有 0 个优势。

于 2015-07-28T11:35:05.010 回答
0

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

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 组合框中定位您的实现方法更加困难)

于 2015-07-28T11:40:06.640 回答