我知道我们可以使用.ToDictionary(t =&gt; t.Key,t =&gt; t.Value)将linq结果集转换为Dictionary集合,但我正在寻找更多内容。我想将给定的linq结果转换为IEnumerable<Dictionary<string, object>>
,这就是我要找的内容:
这是我的linq查询:
var query = from v in dbContext.Persons
where !v.InActive
select new
{
v.PersonId,
v.Name,
v.DateOfBirth,
};
this.Persons = query.ToDictionaryCollection();
这是ToDictionaryCollection的样子:
public static IEnumerable<Dictionary<string, object>> ToDictionaryCollection<T>(this IEnumerable<T> collection) where T : class
{
if (collection == null || collection.Count() == 0)
{
return new List<Dictionary<string, object>>();
}
Type givenType = collection.First().GetType();
PropertyInfo[] properties = givenType.GetProperties(BindingFlags.Instance | BindingFlags.Public);
return collection
.Select(entity =>
{
return properties.Select(prop => new { Key = prop.Name, Value = prop.GetValue(entity) }).ToDictionary(prop => prop.Key, prop => prop.Value);
});
}
根据目前的实施情况,我相信在每个实体上使用反射会受到惩罚。有没有更好的方法,使用lambda表达式树或类似的东西?
注意:以上代码适用于Windows Phone 8和Windows Store 8.1应用程序。
谢谢, Binoy
答案 0 :(得分:0)
看起来你正试图做一些与RouteValueDictionary
世界System.Web
非常相似的事情。您将无法绕过需要进行反思,但您可能会看到Microsoft通过查看their source code来解决此问题,从而获益。
如果您创建了类似于他们的Dictionary类(例如“DynamicDictionary
”),那么您可以将方法更改为:
if (collection == null)
{
return new List<Dictionary<string, object>>();
}
return collection.Select(e => new DynamicDictionary(e));
当然,我建议让你的方法返回一个IDictionary
(甚至IReadOnlyDictionary
接口,这样你就不会与特定的字典实现紧密耦合。
答案 1 :(得分:0)
好像您的代码完全符合您的要求。你可以改变一些小事:
变化:
Type givenType = collection.First().GetType();
到
Type givenType = typeof(T);
并且还改变了这个:
return properties.Select(prop => new { Key = prop.Name, Value = prop.GetValue(entity) }).ToDictionary(prop => prop.Key, prop => prop.Value);
到
return properties.ToDictionary(prop => prop.Name, prop => prop.GetValue(entity));
如果您尝试在类上定义所有属性并返回其C#名称,则无法避免反射。仅获取您需要的特定属性的值以及在其他位置定义名称(例如在视图中)更有意义。但这种设计选择取决于你。
答案 2 :(得分:0)
您可以为每个属性创建一个getter委托,并重用它们而不是调用prop.GetValue()
。
如果您正在迭代的集合足够大,这将是有益的。
var properties = typeof (T).GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Select(
p =>
new
{
Name = p.Name,
Getter = (Func<T, object>) Delegate.CreateDelegate(typeof (Func<T, object>), p.GetGetMethod())
})
.ToList();
return collection.Select(i => properties.ToDictionary(p => p.Name, p => p.Getter(i)));