我正在尝试将Dictionary对象列表转换为数据集。 List来自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 :(得分: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>
。
但无论如何,第二个重载应该具有与第一个相同的通用参数。它将是IList
IDictionary
的{{1}},因此它应采用以下形式:
public static DataSet ToDataSet<TKey, TValue>(this IList<IDictionary<TKey, TValue>> currentList)
{
// ...
}
此处只有2种未知类型,TKey
和TValue
,并且会照常隐含。
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>();
答案 1 :(得分:0)
Jeff M对于为第一种方法指定泛型类型参数的冗余是正确的。
不幸的是,第二种方法的签名使得编译器无法推断出类型参数。一种选择是将签名更改为:
public static DataSet ToDataSet<TKey,TValue>
(this IList<Dictionary<TKey,TValue>> currentList)
并删除对Enumerable.Cast
的多余调用。
这将有两个好处:
List<int>
作为参数。通过以下两项更改,您可以执行以下操作:
Dictionary<string, int> dict = ...
DataSet dictDs = dict.ToDataSet();
List<Dictionary<long, object>> list = ...
DataSet listDs = list.ToDataSet();
答案 2 :(得分:0)
您的方法调用无需指定类型,即:
IDictionary<string, int> test = new Dictionary<string, int>();
// later on.
test.ToDataSet(); // is already valid