2009-06-17 53 views
8

我正在與第三方C#類,有很多偉大的方法和屬性 - 但隨着時間的推移,我需要擴展與我自己的方法和屬性的類。如果它是我的代碼,我只是將該類用作我的基類,並在頂部添加我自己的屬性和方法 - 但該類具有內部構造函數。 (在我看來,它是建立在第一個內部的構造函數的簡短選擇 - 爲什麼限制子類的能力?)有沒有一種方法可以從具有內部構造函數的類派生?

我唯一能想到的就是在我的類上創建方法/屬性,只需調用他們的 - 但它是數英畝的代碼,而且,它只是不「感覺」正確。

有什麼方法可以使用這個類的基類嗎?

+1

第一部分:http://blogs.msdn.com/ericlippert/archive/2008/09/26/preventing-third-party-derivation-part-one.aspx – 2009-06-17 06:00:40

+1

第二部分:http://blogs.msdn .com/ericlippert/archive/2008/10/06/prevent-third-party-derivation-part-two.aspx – 2009-06-17 06:01:39

回答

0

我不會討論是否可以圍繞第三方課堂構建自己的Facade。以前的作者是對的,圖書館的設計可能不會允許這樣做。假設他們有一些耦合類,它們具有應該按特定順序初始化的單例,或者類似的東西 - 可能會有很多第三方開發人員從不關心的設計錯誤(或功能),因爲他們不認爲您會使用他們的圖書館就這樣。

但是OK,讓我們假設,建立一個門面是不是一個不可能完成的任務,而你其實只有一個問題 - 有你周圍寫包裝方法太多,這是不好做此手動。

我看到3個解決方案就是爲了解決這個問題

1)我想,新的「動態」類型的.NET 4.0將允許您要解決這個問題,而無需編寫「千畝的代碼」 你應該將第三方類的實例作爲具有動態關鍵字的私有成員封裝到您的類中 您的類應該從Dynamic派生或實現IDynamicObject接口。你將不得不實施GetMember/SetMember功能,將所有呼叫轉發給第三方類的封裝實例

嗯,C#4.0是一個未來,讓我們上其他解決方案請參見:

2)不要寫代碼如果您有大量的公共方法(比如超過100),請手動進行。我會寫一個使用反射的小控制檯應用程序,並找到所有公共成員,然後自動生成代碼來調用封裝的實例。例如

public type MethodName(params) 
{ 
    this.anInstanceOf3rdPartyClass.MethodName(params); 
} 

3)您可以像2一樣,但藉助現有的反射工具,例如RedGate .NET Reflector。它會幫助你列出所有的類和方法簽名。然後,將所有這些粘貼到Word中,並使用一個簡單的VB宏就可以生成與2中相同的代碼。 備註:只要您不復制代碼,但只複製方法簽名即可,我不認爲你會違反許可協議,但無論如何它值得重新檢查

2

僅當您的課程與您想要繼承的課程位於同一個程序集中時。內部構造函數將抽象類的具體實現限制爲定義該類的程序集。包含內部構造函數的類不能在程序集外實例化。

2

聽起來像是擴展方法一個完美的應用程序:

MSDN extension method docs

「擴展方法使你‘增加’的方法,以現有的類型而無需創建一個新的派生型,重新編譯,或以其他方式修改原始類型。擴展方法是一種特殊的靜態方法,但它們被稱爲擴展類型的實例方法。對於用C#和Visual Basic編寫的客戶端代碼,調用擴展方法和方法之間沒有明顯區別實際上是在一種類型中定義的。「

2

如果該類有一個內部構造函數,並且沒有公共構造函數,那麼這表明設計人員不打算將其細分爲子類。在這種情況下,你可以使用封裝,或者你可以使用擴展方法。

5

你問:「爲什麼限制子類的能力?」

因爲爲繼承設計是棘手的,特別是如果您正在設計其他開發人員繼承您的類。正如Josh Bloch在Effective Java中所說的那樣,您應該設計繼承或禁止它。在我看來,除非你有充分的理由去設計繼承,否則你不應該這樣做。

該類是否實現了一個也可以實現的接口(可能通過將大多數調用代理回原始實例)?在這裏通常沒有真正優雅的答案 - 最好的解決方案將取決於具體情況,包括您想要添加到班級中的內容。

如果您沒有添加任何更多的狀態 - 只是方便的方法,有效的 - 然後擴展方法可能適合你。但是它們不會更改對象能夠存儲的數據,因此如果您需要添加自己的專用數據,那將無法工作。

1

Resharper有一個很好的功能來創建委派成員。

Here是您可以使用它做的一個示例。它需要幾秒鐘。

相關問題