将KeyValuePair转换为LINQ查询中的匿名类型

时间:2012-06-25 14:29:50

标签: c# .net json linq

我有一个IEnumerable<KeyValuePair<string,string>>,理想情况下,我想要一个匿名对象,它将键作为属性名称,值作为属性值。

我尝试了各种选择表达式(其中没有一个甚至编译过......)和使用ExpandoObject的方法(见下文),但没有成功。有没有办法做到这一点?如果可能的话,我想避免对集合进行额外的显式迭代(即使用某种LINQ语句完成所有操作)。

这是我到目前为止所尝试过的。我希望它也澄清了我想要做的事情:

var kvps = getProps(); // returns IEnumerable<KeyValuePair<string,string>>

dynamic o = new ExpandoObject();
foreach (var kvp in kvps)
{
    o.Add(kvp);
}

这在编译时没问题,但在运行时我得到一个YSOD说明'System.Dynamic.ExpandoObject'不包含'添加'的定义 - 我猜它有效在编译时,因为o是动态的,所以编译器无法知道自实例化以来是否已向其添加了方法.Add()。奇怪的是,MSDN documenation page for ExpandoObject .Add()上的内容被列为几种“明确实现的接口方法”之一。

我没有必要把它变成一个动态对象 - 我只需要根据键值对的键和值获得具有属性名称和值的东西。

更新:嗯,这很尴尬。事实证明这也是一个XY问题。

我正在尝试使用ASP.NET MVC的内置功能将此呈现给JSON,只需在我的控制器中返回Json(data)即可。答案都能很好地完成我第一次提出的问题,但是当我将这个对象传递给data时,我仍然无法得到我想要的东西:

// What I get:
[
   { Key: 'firstkey', Value: 'FirstValue' }, 
   { Key: 'secondKey', Value: 'secondValue' } 
]

// What I want:
{ firstKey: 'FirstValue', secondKey: 'secondValue' }

显然,添加了相关属性的ExpandoObject没有删除它 - 它在渲染之前被转换为字典...

3 个答案:

答案 0 :(得分:6)

填充时,您需要将ExpandoObject用作IDictionary<string, object>

var kvps = getProps(); // returns IEnumerable<KeyValuePair<string,string>>

IDictionary<string, object> o = new ExpandoObject();
foreach (var kvp in kvps)
{
    // Or use Add(kvp.Key, kvp.Value), if you want
    o[kvp.Key] = kvp.Value;
}

dynamic d = o;
// Now you can use the properties

答案 1 :(得分:4)

ExpandoObject明确实现IDictionary<string, object> - 因此您需要先将其强制转换为:

var kvps = getProps();
dynamic o = new ExpandoObject();
var dict = o as IDictionary<string, object>;
foreach (var kvp in kvps)
{
    dict.Add(kvp.Key, kvp.Value);
}

现在您可以按预期使用o

var example = o.YourKey;
  

我正在尝试使用ASP.NET MVC的内置功能将此呈现给JSON,只需在我的控制器中返回Json(数据)即可。

有趣。

为此,您序列化字典,而不是ExpandoObject。 MVC 3的JSON序列化器已经用字典做了。您所要做的就是将IEnumerable<KeyValuePair<string, object>>转换为字典:

var kvps = getProps();
var dictionary = kvps.ToDictionary(k => k.Key, v => v.Value);
return Json(dictionary, JsonRequestBehavior.AllowGet); //take out allow get if you don't need it.

无需动态。

答案 2 :(得分:1)

我认为你必须将你的expando对象转换为IDictionary并调用Add(string,object)