在 LINQ 查询中将 KeyValuePair 转换为匿名类型
Posted
技术标签:
【中文标题】在 LINQ 查询中将 KeyValuePair 转换为匿名类型【英文标题】:Convert KeyValuePair to anonymous type in a LINQ query 【发布时间】:2012-06-26 19:45:36 【问题描述】:我有一个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' 不包含 'Add' 的定义 - 我猜它在编译时有效时间因为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
并没有删减它 - 它在渲染之前被强制转换为字典...
【问题讨论】:
是的,我见过this question。那真是一个XY-problem,在没有帮助我的情况下解决了。 【参考方案1】:您需要在填充时将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
【讨论】:
这给了我第一行的编译错误 (IDictionary<object, object> o = new ExpandoObject();
),但既然是你,我认为编译器是错误的。我猜它认为应该是IDictionary<string,object>
- 我会立即告诉它你说过要这样做。
@TomasLycken:已将我的帖子编辑为 object
更改为 string
,谢谢。其余的看起来都取决于 JSON 转换器。您可能会发现另一种 JSON 序列化框架(例如 JSON.NET)可以修复它。【参考方案2】:
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(data)。
有趣。
为此,您需要序列化字典,而不是 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.
不需要动态。
【讨论】:
谢谢!但是,我有点太快来制定我的问题 - 请查看我的更新... @TomasLycken 我在更新代码时遇到了一个小问题,我有ToDictionary(k => k.Value, v => v.Value);
而不是ToDictionary(k => k.Key, v => v.Value);
实际上,它对我来说效果很好。为了清楚起见,我将其更改为ToDictionary(kvp => kvp.Key, kvp => kvp.Value)
,然后它完全符合我的要求 =)【参考方案3】:
我认为您必须将您的 expando 对象转换为 IDictionary 并调用 Add(string, object)
【讨论】:
以上是关于在 LINQ 查询中将 KeyValuePair 转换为匿名类型的主要内容,如果未能解决你的问题,请参考以下文章