2016-05-13 87 views
1

我有一組我無法觸及的類對象。他們都有一個ID屬性,我想以通用的方式訪問其他功能。創建多對一的關係

爲了簡單起見,這裏是我的問題的一個例子。

class Example1 { 
    int ID { get; set;} 
} 
class Example2 { 
    int ID { get; set; } 
} 

我不能夠編輯這兩種類別或他們是在圖書館。

我也有一個期望中的標識可以來自Example1Example2功能。爲了解決這個問題,我提出了一些解決方案,但很好奇,解決這個問題的正確方法是什麼。

我能:

  1. 使用動態類以訪問各種類的ID。
  2. 使用反射從任何給定類型拉出ID參數。
  3. 通過創建一個新的類使用一個奇怪的繼承,以便Example1ViewModel : Example1, IIdentifiableObject,然後期望在我的功能IIdentifiableObject和實施一個拷貝構造函數中Example1ViewModel處理採集數據
  4. 寫一個單獨的過濾功能,可以從中提取出相關零件無論是上課還是提供結果。

這些解決方案對我來說都不是特別好。我應該如何在代碼中處理這樣的多對一關係,並且C#提供了哪些工具來處理這個問題?對於類

public static class MyExtensions 
    { 
     public static int GetId(this Example1 ex) 
     { 
      return ex.Id; 
     } 

     public static int GetId(this Example2 ex) 
     { 
      return ex.Id; 
     } 
    } 
+1

你可以添加一個擴展方法到類Example1,Example2嗎? –

回答

0

下面是我們最終使用的解決方案和原因。

我們正在使用的繼承結構,它採用以下兩個基本類別:

FooExample 
BarExample 

和包裝他們在以下

IExample 
FooExampleModel : IExample 
BarExampleModel : IExample 

兩個FooExampleModelBarExampleModel有構造函數接受類他們正在包裝。

這樣做的重要性在於它允許我們創建接受IExample實例的方法,而無需事先操作數據。另外,與使用動態類型或反射不同,此解決方案爲我們提供編譯時錯誤檢查。

不幸的是使用擴展方法不起作用。雖然它允許我們在兩種不同的對象類型上調用相同的方法,但我們希望它們不允許將這些對象作爲泛型類型傳遞給單獨的函數。

所有這些的結果是,這是現在能夠:

var foos = new List<FooExample>(); //Pretend there is data here 
var bars = new List<BarExample>(); 
var examples = foos.Select((foo) => (IExample)new FooExampleModel(foo)) 
        .Concat(bars.Select((bar) => (IExample)new BarExampleModel(bar))) 
        .ToList(); // Force evaluation before function call 
DoSomethingOnIExamples(examples); 

除了這似乎是實現這一目標的最佳方式略微毛LINQ查詢(DoSomethingOnIExamples(...)是受理IEnumerable<IExample>參數的函數) 。顯然這個解決方案變得不太好,因爲更多的類型被添加到這個混合。

2

可能採用的解決方案擴展方法,您可以添加一個靜態方法使用反射:

public static int GetId(object obj) 
    { 
     Type type = obj.GetType(); 
     return Convert.ToInt32(type.GetProperty("ID").GetValue(obj, null)); 
    } 

然後,你可以與任何對象調用它來獲得id屬性值。

+0

這工作,但仍需要一些包裝。我需要從我的函數外部調用這些函數,然後將結果傳入。這是一個很好的解決方案,但是您是否知道一種限制函數的方法,只接受'Example1'或'Example2',而不是String?還是需要包裝?我一直沒有想到在函數前面用'examples.Select((ex)=> ex.GetId())'這樣的方法。 –

+0

我不認爲我站在你面前quesion。擴展方法的意思是,比現在當你創建一個對象時,它具有該功能。即:Example1 ex = new Example()。你有ex.GetId()。 –

+0

這裏的目標似乎是將事物置於相同類型下,或允許其他通用實現。我不確定我通過添加擴展方法獲得了什麼,除非我可以要求它們以某種方式存在。通過調用GetId()與簡單調用對象ID屬性,我可以獲得什麼? –

0

+0

我對反射或動態類解決方案的關注是,都需要基於運行時的錯誤檢查。如果可能的話,在編譯時得到錯誤將是理想的。 –