2015-07-28 82 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組合框中定位您的實現方法變得更加困難)