2011-07-27 41 views
2

我最近來到了這個兩難問題:假設我想用兩個庫每個人的定義了一個接口,用於消費者和耗材:用C#接口設計問題

#region Library A 
// This region represents a library (A) defining some interfaces 

/// <summary> 
/// Interface to be implemented by any processor of type A 
/// </summary> 
interface AProcessor 
{ 
    void Process(AProcessable a); 
} 

/// <summary> 
/// Interface to be implemented by any object processable by a processor of type A 
/// </summary> 
interface AProcessable 
{ 
    int MyPropertyA { get; set; } 
} 
#endregion 


#region Library B 
// This region represents a library (B) defining some other interfaces 

/// <summary> 
/// Interface to be implemented by any processor of type B 
/// </summary> 
interface BProcessor 
{ 
    void Process(BProcessable a); 
} 

/// <summary> 
/// Interface to be implemented by any object processable by a processor of type B 
/// </summary> 
interface BProcessable 
{ 
    int MyPropertyB { get; set; } 
} 
#endregion 

然後,在我的應用程序,我實現了從每個庫同時實現消費品接口耗材類型:

/// <summary> 
/// A type processable by processors of type A and processors of type B. 
/// </summary> 
class Processable : 
    AProcessable, 
    BProcessable 
{ 
    // Implements interface AProcessable 
    public int MyPropertyA { get; set; } 

    // Implements interface BProcessable 
    public int MyPropertyB { get; set; } 
} 

我能夠實現消費型處理的,它實現AProcessable和BProcessable的對象的消費類型:

/// <summary> 
/// A processor that implements an A-type processor and a B-type processor. 
/// </summary> 
class Processor : 
    AProcessor, 
    BProcessor 
{ 
    // I thought that Process method would implement AProcessor.Process() and 
    // BProcessor.Process() as it expects a Processable object as parameter which 
    // implements AProcessable and BProcessable, but it doesn't. 
    // Compiler rises an error telling that Processor doesn't implement neither 
    // AProcessor.Process() nor BProcessor.Process() 
    /* 
    public void Process(Processable a) 
    { 
     throw new NotImplementedException(); 
    } 
    */ 


    // Implementing both methods does not work because it creates ambiguity: when 
    // we call Processor.Process(p) being "p" a Processable object the compiler 
    // doesn't know if it has to call Processor.Process(AProcessable) or 
    // Processor.Process(BProcessable). 
    /* 
    public void Process(AProcessable a) 
    { 
     throw new NotImplementedException(); 
    } 

    public void Process(BProcessable a) 
    { 
     throw new NotImplementedException(); 
    } 
    */ 
} 

¿什麼是我的設計錯誤,什麼是正確的方法?

在此先感謝。

回答

1

我不認爲這裏需要明確的接口實現,因爲這兩種處理方法的簽名之間沒有衝突(參數的類型AP處理AProcessor和BProcessable第二)。由於我想象着對於可處理實例,您希望兩個處理都被執行,我會這樣實現它:

public class Processor : AProcessor, BProcessor 
{ 
    #region AProcessor Members 

    public void Process(AProcessable a) 
    { 
     throw new Exception("The method or operation is not implemented."); 
    } 

    #endregion 

    #region BProcessor Members 

    public void Process(BProcessable a) 
    { 
     throw new Exception("The method or operation is not implemented."); 
    } 

    #endregion 

    public void Process(Processable a) 
    { 
     Process((AProcessable)a); 
     Process((BProcessable)a); 
    } 
} 
+0

是的,夥計,它發揮了訣竅。 如果我可以保留Process(AProcessable)和Process(BProcessable)是私人的,那將是完美的,但我認爲這是不可能的。 非常感謝。 –

+0

不可能讓它們成爲私人的,因爲正如亞當寫道的,屬於界面的所有東西都必須公開 –

4

您正在尋找顯式接口實現。此鏈路具有教程:

http://msdn.microsoft.com/en-us/library/aa288461(v=vs.71).aspx

基本上,該方法簽名示出了接口類型:

void BProcessor.Process(BProcessable b) 
{ 

} 

,只能用一個直接引用被訪問以BProcessor

BProcessor b; 
b.Process(null); 

BProcessor的推斷引用不適用於顯式實現:

Processor p; 
p.Process(new BProcessable()); // This won't compile. 

這使您可以實現具有衝突成員名稱的接口。如果他們有衝突的類型名稱,則需要開始查看名稱空間衝突。

您會注意到一個明確的實現,因爲當您獲得Intellisense for Processor時,它將丟失Process(BProcessable b)

如果在處理過程的代碼恰好是共享的,你可以做到以下幾點:

public void Process(Processable p) 
{ 

} 

void AProcess.Process(AProcessable a) 
{ 
    Process((Processable)a); 
} 

void BProcess.Process(BProcessable b) 
{ 
    Process((Processable)b); 
} 

不過,我個人會避免這種類型的前鋒鑄造的,你不能保證(比你其他完全控制代碼)以獲得Processable類型。

+0

是啊!這就說得通了。無論如何,AProcess.Process(AProcessable a)和BProcess.Process(BProcessable b)是私有的編譯器仍然因未實現的接口投訴。 下面弗朗切斯科指向類似的解決方案使這些方法公衆和避免wroks精顯式接口實現。我很想讓他們保持私密,但我知道這是不可能的。 非常感謝。 –

+0

@大衛啊我看到了,他的位置很好。說實話,我沒有深入研究你使用的類型結構。接口成員必須是公共的,因爲該接口被設計爲供其他代碼使用。私人界面成員沒有意義。 –

2

使用顯式接口實現:

void AProcessor.Process(AProcessable a) 
{ 
    throw new NotImplementedException(); 
} 

void BProcessor.Process(BProcessable a) 
{ 
    throw new NotImplementedException(); 
} 

使用顯式接口實現禁用叫什麼方法自動查找。當你調用這些方法,您需要將對象轉換爲一個接口:

Processor p; 
Processable pa; 
((AProcess)p).Process(pa); 

除了處理與衝突的名稱/方法簽名明確實現這種情況,也可用於隱藏(或至少使其更難使用)接口所需的方法,但對於特定的類沒有意義。

+0

我不知道顯式實現。非常感謝您的幫助。 –

0

在您的第一次嘗試中,使用一種方法,您並未實現接口的精確定義,該接口不希望將可處理對象作爲參數,而是AProcessable和BProcessable,具體取決於您想要的對象。

第二,正如其他人所指出的那樣,需要使用顯式的實現,這樣就可以清楚地定義你要調用其中兩個。

如果你想調用它們兩個,那麼你需要做兩個單獨的調用 - 你可以實現一個方法處理這個類,然後調用AProcessable.Process和BProcessable.Process。但它必須明確地完成,而不僅僅是通過繼承和接口。

+0

您的解決方案與其他解決方案一致。他們幫了我很多。謝謝。 –

0

每個人都提供了精細解釋相關爲什麼代碼不能正常工作的技術方面的原因,但是我認爲你瞭解這些你的問題問的設計問題是什麼,如何解決這個問題....所以我來補充我的2c混合。

基本上你正在試圖二者混合兩個原本完全不同的概念成一個邏輯控制一段代碼(處理器類)。

通過定義可以處理的兩種不同的事物和這些事物的處理器必須處理的兩種方法,您正在設置一個系統,以完全不同的方式處理兩個不同的事物......因此它們是不一樣的,不能合併。

至於另一個關於如何「修復」問題的解決方案(我使用「修復」這個詞,因爲很難在不知道問題的上下文的情況下提出替代解決方案),您需要找到一種方法來表示兩種可處理的類型和處理器以一種常見的方式......或者只是不混合具體處理器實現中的兩個概念。

更多地瞭解問題的實際情境,將有助於我們提供更準確的建議! :)

祝你好運!

+0

是的,你說得對。我明白爲什麼它不起作用,我懷疑是一個糟糕的設計問題。 我明白我想要做的是有點棘手。這在我工作的環境中很有意義,但我也明白,這不是一種常見的情況。你的抽象讓我澄清了一些想法。謝謝。 –