2014-05-22 76 views
1

我有一些應該生成圖表的類。我有三個類爲圖表系列使用不同類型的數據。我將提供這些類的屬性,以避免混淆:)如何使用C#泛型將類的對象轉換爲類型T的對象?

public class PointBase 
{ 
    public decimal X { get; set; } 
} 

public class Point : PointBase 
{ 
    public decimal Y { get; set; } 
} 

public class Bubble : Point 
{ 
    public decimal Size { get; set; } 
} 

這三個類用作圖表系列中的基本數據。一系列圖表在其他三個類(圖表的一個)中被表示爲字典對象。我不會提供圖表類的代碼,以專注於具體問題。我將只提供這些類的名稱:

  1. CoordinateChart(使用PointBase作爲基本數據段)。
  2. ScatterChart(使用Point)。
  3. BubbleChart(使用泡泡)。

我有以下的方法,爲我所有的圖表類做了完全相同的算法。這就是爲什麼我決定使用泛型的方法。

public Dictionary<string, T[]> GenerateSeriesDataDictionary<T>(string[] series, string[] categories) where T : PointBase, new() 
    { 
     // Create a new Dictionary. 
     Dictionary<string, T[]> seriesData = new Dictionary<string, T[]>(); 

     // Gets the number of categories and assigns the categoriesNumber variable with the returned value. 
     int categoriesNumber = categories.Length; 

     foreach (string serie in series) 
     { 
      Dictionary<string, T> categoriesData = (Dictionary<string, T>)GetCategoriesData(serie); 

      // Create a new array of Ts that will store the data for the current serie. 
      T[] dataArray = new T[categories.Length]; 

      for (int i = 0; i < categoriesNumber; i++) 
      { 
       // If the serie contains a value for the current category, store it in the array. 
       // Otherwise, set the value of the current element of the array to the default one. 
       dataArray[i] = categoriesData.ContainsKey(categories[i]) ? categoriesData[categories[i]] : new T(); 
      } 

      // Add the dataArray to the seriesData Dictionary. 
      seriesData.Add(serie, dataArray); 
     } 

     return seriesData; 
    } 

因此,上述方法接收兩個字符串數組。第一個代表該系列的名稱,例如「東京」和「倫敦」。第二個代表圖表類別的名稱 - 例如,月份的名稱 - 「1月」,「2月」等。

該方法應該創建一個Dictionary對象,該對象使用名稱作爲一個關鍵和相應的數組對象,代表每個類別的數據(在我的情況 - 每個月)。例如,Dictionary中的單個鍵值對應如下所示: 鍵:「London」;值:17,16,20,25(假設數據代表每個月的最高溫度)。

我基本上執行相同的算法,每當我創建一條線,一個分散或氣泡圖(由CoordinateChart,ScatterChart和BubbleChart類表示)。唯一不同的是我生成的字典的類型。

  1. CoordinateChart使用詞典(字符串,PointBase的[])
  2. ScatterChart使用Dicitonary(字符串,點[])
  3. BubbleChart中使用詞典(字符串,氣泡[])

我用'('和')代替'<'和'>'字符,因爲它們似乎消失了:)

這就是爲什麼我決定把第e邏輯應該在單獨的方法中生成Dictionary對象,然後在每個類中重寫此方法。

我的方法是這樣的:

public virtual Dictionary<string, PointBase> GetCategoriesData(string serie) 
    { 
     Dictionary<string, PointBase> categoriesData = sqlResultDataTable.AsEnumerable() 
      .Where(row => row["City"].ToString() == serie) 
      .Select(row => new KeyValuePair<string, PointBase>(row["Month"].ToString(), new PointBase(decimal.Parse(row["Temperature"].ToString())))) 
      .ToDictionary(item => item.Key, item => item.Value); 

     return categoriesData; 
    } 

這種方法基本上得到所有代表「月」和「溫度」值意甲的鍵值對(例如,「倫敦」)。

所以,我正在做這一切,以便有代碼的可重用性。否則,我可以在所有三個類中都做同樣的事情,並且我可以在每個類中提供GenerateSeriesDataDictionary方法的單獨實現,但我認爲這不是一個好方法。

一切都是好的,但我得到一個錯誤在這條線:

Dictionary<string, T> categoriesData = (Dictionary<string, T>)GetCategoriesData(serie); 

錯誤狀態的消息:「不能型詞典(串,PointBase的)轉換成詞典(串,T)」。

我換成 '(' 和 ')' 的 '<' 和 '>' 字符,因爲他們似乎消失了:)

我能做些什麼?

+0

爲什麼你不能僅僅通過categoriesData字典環和匹配使用'價值。價值是Point'或'。價值是泡沫每當你需要使用集合? –

回答

1

使用泛型類型參數創建基類/接口。

public abstract class Chart<T> where T : PointBase, new() 
{ 
    public abstract IDictionary<string, T> GetCategoriesData(string serie); 

    public IDictionary<string, T[]> GenerateSeriesDataDictionary<T>(string[] series, string[] categories) 
    { 
     // Call GetCategoriesData, etc. 
    } 
} 

然後創建派生類與特定的點類型:

public class ScatterChart : Chart<Point> 
{ 
    public override IDictionary<string, Point> GetCategoriesData(string serie) 
    { 
     // Create new Point and set its properties. 
     // We know it is a Point because we specified it in the class generic type. 
    } 

    // ... 
} 

public class BubbleChart : Chart<Point> 
{ 
    public override IDictionary<string, Bubble> GetCategoriesData(string serie) 
    { 
     // Create new Bubble and set its properties. 
     // We know it is a Bubble because we specified it in the class generic type. 
    } 

    // ... 
} 
+0

這對於基類(CoordinateChart)是可以的。但是我希望ScatterChart能夠從CoordinateChart中得到字符串(字符串,點)。我想以與設置X屬性相同的方式在GetCategoriesData方法中設置Point的Y屬性。那麼,我怎麼能做到這一點? – Yulian

+0

啊,在這種情況下,你需要讓Chart類自己派生自一個通用的接口或類。然後每個類都可以指定它的覆蓋類型。給我一些時間來編輯我的答案。 – metacubed

+0

@Julian現在檢查答案..這是否解決您的問題? – metacubed

0

您不能將Dictionary<string, PointBase>投射到例如Dictionary<string, Bubble>,所以這就是爲什麼你的代碼不會編譯。它們不是同一件事。

您或者需要聲明categoriesData爲Dictionary<string, PointBase>,或者使GetCategoriesData()方法爲通用。

0

這是一個類型爲variance的問題,協方差更具體。

淨讓你只能做一個安全的協方差,否則將意味着

Dictionary<string, Bubble> bubbles = GetBubbles(); 
Dictionary<string, PointBase> points = bubbles; 

points["London"] = new Point(); //crash, not a Bubble 

考慮使用IEnumerable即與協變泛型類型的只讀接口。

相關問題