2013-07-12 75 views
9

C#中的擴展類可能不是通過僅添加函數而是通過屬性來擴展。例如:我有一個我依賴的標準DLL庫,供應商不想修改它。C#通過添加屬性來擴展類

已經在整個代碼中已經廣泛地使用了DataCell類,並且現在才意識到我需要爲它添加一個額外的屬性,因爲創建一個從此類繼承的新擴展類只是看起來不會工作+很多重寫。

DATACELL [元數據]

public class DataCell : Message 
{ 
public int Field1; 
public int Field2; 
public DataCell() 
{ 
.. 
} 
.. 
} 

基本上我想添加一個公衆詮釋標誌;這個班。所以我現在可以不用重寫任何東西,(新的DataCell).Flags = 0x10;

+1

你不能有擴展屬性,但你可以繼承一個類,添加屬性 – Sayse

+0

什麼你在這種情況下,「延長」意思?你有源代碼嗎?或者你想使用擴展屬性(你不能)?或從DataCell繼承好嗎? – Tim

+0

通過擴展我的意思是這個類在供應商.dll庫中大量使用,我正在使用。創建像ExtDataCell:DataCell不是一個選項,因爲我基本上需要重寫.dll庫。所以我想以某種方式能夠做到這一點,所以來自供應商.dll的DataCell可以擁有它沒有atm的Flags屬性。 (沒有修改供應商DLL) –

回答

6

首先,你應該重新考慮你的方法。 但如果一切都失敗了,這裏是你如何能排序屬性添加到一個密封類:

using System; 
using System.Runtime.CompilerServices; 

namespace DataCellExtender 
{ 

    #region sample 3rd party class 
    public class DataCell 
    { 
     public int Field1; 
     public int Field2; 
    } 
    #endregion 

    public static class DataCellExtension 
    { 
     //ConditionalWeakTable is available in .NET 4.0+ 
     //if you use an older .NET, you have to create your own CWT implementation (good luck with that!) 
     static readonly ConditionalWeakTable<DataCell, IntObject> Flags = new ConditionalWeakTable<DataCell, IntObject>(); 

     public static int GetFlags(this DataCell dataCell) { return Flags.GetOrCreateValue(dataCell).Value; } 

     public static void SetFlags(this DataCell dataCell, int newFlags) { Flags.GetOrCreateValue(dataCell).Value = newFlags; } 

     class IntObject 
     { 
      public int Value; 
     } 
    } 


    class Program 
    { 
     static void Main(string[] args) 
     { 
      var dc = new DataCell(); 
      dc.SetFlags(42); 
      var flags = dc.GetFlags(); 
      Console.WriteLine(flags); 
     } 
    } 
} 

請不要這樣做,除非你真的必須。如果你有一個更清晰的解決方案,而你跳過這個稍微黑客的方法,這個代碼的未來維護者可能會對你有一些強烈的話。

+1

這絕對是一個有趣的解決方法。我會首先探索清潔劑的選擇,但至少值得考慮。 –

+0

@JonSkeet是的,我忘了明確提及這是多麼可怕,而且不應該這樣做。我會編輯它。 – dss539

+0

哇這個問題打10k意見。接受這是最好的答案,因爲這似乎是我當時需要的。不確定的表現壽。 –

7

那麼你當然可以擴展一個類,只添加字段/屬性(雖然我不鼓勵按照你的樣本使用公共字段)。但是,除非其他代碼使用您的新類,這些字段將不存在於創建的對象中。例如,如果其他代碼有:

DataCell cell = new DataCell(); 

那麼不會有你Field1Field2領域。

如果基類的每一個情況下確實應該有這些領域,你會更好的工作如何更改基類而不是擴展。

如果你想知道你是否能作爲擴展以同樣的方式增加「擴展字段」 方法添加(例如public static void Foo(this DataCell cell))則沒有,這是不可能的。

+0

問題是這個類廣泛用於供應商提供的另一個類。因此,爲每個繼承擴展類,需要擴展一堆其他類並重寫很多。 好的謝謝 –

+0

@VansS:嗯,我還不清楚基本上基本類是否應該有額外的字段,或誰擁有基類。但是,您不能只將字段添加到您不擁有的類中。 –

+0

@JonSkeet - 你是否介意批評我對這種情況的回答? http://stackoverflow.com/a/17617683/55721 – dss539

2

有兩種方法將屬性添加到現有類

  1. 添加部分類,但是這不會爲你工作,因爲局部類應該在同一程序。

  2. 繼承此類在一個不同的類,據我所知,這將是一個更好的解決方案。

不,你不能像擴展方法那樣使用擴展屬性。

相關問題