2015-07-28 37 views
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(); 
    } 
} 
+2

您可以更新代码以使用IFoo而不是Foo吗?这在我看来是令人困惑... – 2015-07-28 11:22:49

+0

完成 - 对不起,通常我尊重代码约定... – Thaoden

回答

8

通常情况下,依赖注入的目的是脱钩,您可以通过注射抽象到其客户实现:

public class Baz 
{ 
    private readonly IFoo foo; 

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

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

这确保了Baz取决于IFoo,并分离从任何具体实现。

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

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

+0

这就是我想要的。如果出于某种不明确的原因,人们没有注意并写了一个期望具体类的构造函数:'public Baz(Foo1 foo)',那么使用显式接口实现将禁止对对象方法的任何调用。试图将一个具体的实现投入到它的接口中会发出一些警钟,那么,不是吗? – Thaoden

+0

如果你不小心**添加了一个期望具体类的构造函数,那么你刚刚失去了依赖注入目的的解耦。这对服务来说是一个更大的问题,应该在问题的根源上解决,而不是由任意客户端修补。 –

1

如果你的类是容器,那么你使用的界面。所以,没有任何好处。

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

总计:使用容器中的类和测试不当时的优点为0。

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