获取字典列表作为数据集的扩展方法?
我正在尝试将 Dictionary 对象列表转换为数据集。该列表来自 JSON 解析器。我决定以此为契机来学习扩展方法。
单个字典的扩展方法有效,但字典列表的方法对我来说“看起来”不正确,主要是因为调用变成了
DataSet myExampleDataSet = myExampleDictionary.ToDataSet<Dictionary<string,string>,string,string>();
我错过了什么吗?事情真的有必要这么复杂吗?我应该将 Dictionary .ToDataSet 方法放入 foreach 中吗?
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;
}
}
}
I'm trying to cast a List of Dictionary objects to a dataset. The List comes from a JSON parser. I decided to use this as an opportunity to learn about extension methods.
The extension method for a single dictionary works, but the method for a List of Dictionaries doesn't "look" right to me, mainly because the call becomes
DataSet myExampleDataSet = myExampleDictionary.ToDataSet<Dictionary<string,string>,string,string>();
Am I missing something? Does it really have to be this complicated? Should I just throw the Dictionary .ToDataSet method in a foreach?
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;
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
通常不需要显式定义调用泛型方法时使用的泛型类型参数。这些类型将由您调用的参数类型隐含。如果存在歧义,编译器会让您知道。
例如,
糟糕,我没有意识到您重载了
ToDataSet()
。我只看到第一个需要一个IDictionary
。但无论哪种方式,第二个重载都应该具有与第一个重载相同的通用参数。它将是
IDictionary
的IList
,因此应该采用以下形式:这里只有 2 个未知类型,
TKey
和TValue
这将像往常一样被暗示。You generally don't need to explicitly define the generic type arguments used when calling a generic method. The types will be implied by the types of the arguments you are calling with. If there's an ambiguity, the compiler will let you know.
e.g.,
Oops, I didn't realize you overloaded
ToDataSet()
. I only saw the first one which took a singleIDictionary<TKey, TValue>
.But either way, the second overload should have the generic parameters the same as the first. It will be a
IList
ofIDictionary
s so it should be in this form:There are only 2 unknown types here,
TKey
andTValue
and that will be implied as usual.您的方法调用不需要指定类型,这将是:
Your method call needs not specify the types, which would be:
Jeff M 关于为第一个方法指定通用类型参数的冗余的说法是正确的。
不幸的是,第二个方法的签名使得编译器无法推断类型参数。一种选择是将签名更改为:
并删除对
Enumerable.Cast
的冗余调用。这将有两个好处:
List
作为参数传递。通过这两项更改,您可以执行以下操作:
Jeff M is right about the redundancy of specifying the generic type-arguments for your first method.
Unfortunately, the signature of the second method is such that it would not be possible for the compiler to infer the type arguments. One option would be to change the signature to:
and to remove the redundant call to
Enumerable.Cast
.This will have 2 benefits:
List<int>
as an argument.With these two changes, you can do: