获取字典列表作为数据集的扩展方法?

时间:2010-11-15 06:35:15

标签: c# generics extension-methods

我正在尝试将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;
        }



    }
}

3 个答案:

答案 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种未知类型,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>();

答案 1 :(得分:0)

Jeff M对于为第一种方法指定泛型类型参数的冗余是正确的。

不幸的是,第二种方法的签名使得编译器无法推断出类型参数。一种选择是将签名更改为:

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

并删除对Enumerable.Cast的多余调用。

这将有两个好处:

  1. 您不必显式指定泛型类型参数,类型推理器会解决它。
  2. 由于不涉及强制转换,因此操作变为类型安全,因此您将无法传递List<int>作为参数。
  3. 通过以下两项更改,您可以执行以下操作:

    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