2010-11-15 130 views
0

我想將一個Dictionary對象列表轉換爲數據集。該列表來自JSON解析器。我決定以此爲契機來了解擴展方法。擴展方法獲取字典列表作爲數據集?

單個字典工程擴展方法,但對詞典列表不「看」我的權利,主要是因爲該呼叫將變爲

DataSet myExampleDataSet = myExampleDictionary.ToDataSet<Dictionary<string,string>,string,string>(); 

我缺少的東西的方法是什麼?它真的要這麼複雜嗎?我應該在foreach中拋出Dictionary .ToDataSet方法嗎?

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Data; 
using System.Collections; 

//fixed code below 
namespace TT.Utils 
{ 
    public static class DictionaryExtensions 
    { 
     /// <summary> 
     /// Dictionary to DataSet 
     /// </summary> 
     /// <typeparam name="TKey"></typeparam> 
     /// <typeparam name="TValue"></typeparam> 
     /// <param name="currentDictionary"></param> 
     /// <returns></returns> 
     public static DataSet ToDataSet<TKey, TValue>(this IDictionary<TKey, TValue> currentDictionary) 
     { 
      DataSet exportedDataSet = new DataSet(); 
      DataTable exportedDataTable = exportedDataSet.Tables.Add(); 
      foreach (TKey key in currentDictionary.Keys) 
      { 
       exportedDataTable.Columns.Add(key.ToString()); 
      } 
      DataRow newRow = exportedDataTable.NewRow(); 
      foreach (KeyValuePair<TKey, TValue> entry in currentDictionary) 
      { 
       string key = entry.Key.ToString(); 

       string val = string.Empty; 
       if (entry.Value != null) 
       { 
        val = entry.Value.ToString(); 
       } 

       newRow[key] = val; 

      } 
      exportedDataSet.Tables[0].Rows.Add(newRow); 
      return exportedDataSet; 
     } 

     /// <summary> 
     /// List of dictionaries to dataset 
     /// </summary> 
     /// <typeparam name="TKey"></typeparam> 
     /// <typeparam name="TValue"></typeparam> 
     /// <param name="currentList"></param> 
     /// <returns></returns> 
     public static DataSet ToDataSet<TKey,TValue>(this IList<Dictionary<TKey,TValue> currentList) 
     { 
      DataSet exportedDataSet = new DataSet(); 
      DataTable exportedDataTable = exportedDataSet.Tables.Add(); 



      foreach (Dictionary<TKey, TValue> currentDictionary in currentList.Cast<Dictionary<TKey,TValue>>()) 
      { 
       foreach (TKey key in currentDictionary.Keys) 
       { 
        if (!exportedDataTable.Columns.Contains(key.ToString())) 
         exportedDataTable.Columns.Add(key.ToString()); 
       } 
       DataRow newRow = exportedDataTable.NewRow(); 
       foreach (KeyValuePair<TKey, TValue> entry in currentDictionary) 
       { 
        string key = entry.Key.ToString(); 

        string val = string.Empty; 
        if (entry.Value != null) 
        { 
         val = entry.Value.ToString(); 
        } 

        newRow[key] = val; 

       } 
       exportedDataSet.Tables[0].Rows.Add(newRow); 
      } 

      return exportedDataSet; 
     } 



    } 
} 
+0

你'ToDataSet'是把三種類型'<>'。它真的編譯? – xandy 2010-11-15 06:46:11

回答

3

你一般不需要明確定義調用泛型方法時使用的泛型類型參數。這些類型將被你正在調用的參數的類型所暗示。如果有歧義,編譯器會讓你知道。

例如,

IDictionary<string, string> myExampleDictionary = ...; 
DataSet myExampleDataSet = myExampleDictionary.ToDataSet(); 
// equivalent to:   myExampleDictionary.ToDataSet<string, string>(); 

IDictionary<string, int> anotherDictionary = ...; 
DataSet anotherDataSet = anotherDictionary.ToDataSet(); 
// equivalent to:  anotherDictionary.ToDataSet<string, int>(); 

哎呀,我不知道你超載ToDataSet()。我只看到第一個拿了一個IDictionary<TKey, TValue>

但是無論如何,第二次重載應該具有與第一次相同的通用參數。這將是IDictionaryIList A S所以應該以這種形式:

public static DataSet ToDataSet<TKey, TValue>(this IList<IDictionary<TKey, TValue>> currentList) 
{ 
    // ... 
} 

只有2種未知這裏,TKeyTValue和將暗示如常。

IList<IDictionary<string, string>> myList = ...; 
DataSet myDataSet = myList.ToDataSet(); 
// equivalent to: myList.ToDataSet<string, string>(); 

IDictionary<string, int> anotherList = ...; 
DataSet anotherDataSet = anotherList.ToDataSet(); 
// equivalent to:  anotherList.ToDataSet<string, int>(); 
+0

那麼列表類型將成爲第二種方法中唯一的類型參數? – 2010-11-15 06:46:04

+0

上面的代碼是解決方案,加上對第二種方法的更改:簽名變爲公共靜態DataSet ToDataSet (this IList > currentList)//謝謝傑夫! – 2010-11-15 06:51:10

0

Jeff M對於指定第一種方法的泛型類型參數的冗餘是正確的。

不幸的是,第二種方法的簽名是這樣的,編譯器不可能推斷出類型參數。一種選擇是將簽名改爲:

public static DataSet ToDataSet<TKey,TValue> 
    (this IList<Dictionary<TKey,TValue>> currentList) 

,並刪除冗餘呼叫到Enumerable.Cast

這將有2個好處:

  1. 您wan't必須明確地指定泛型類型參數,類型inferencer會弄明白。
  2. 由於不涉及轉換,操作變爲類型安全的,因此您將無法將List<int>作爲參數傳遞。

有了這兩個變化,你可以這樣做:

Dictionary<string, int> dict = ... 
DataSet dictDs = dict.ToDataSet(); 

List<Dictionary<long, object>> list = ... 
DataSet listDs = list.ToDataSet(); 
0

你的方法調用無須指定類型,具體做法是:

IDictionary<string, int> test = new Dictionary<string, int>(); 
// later on. 
test.ToDataSet(); // is already valid