1

我知道我们可以使用 .ToDictionary(t => t.Key, t => 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 应用程序。

谢谢,比诺伊

4

3 回答 3

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# 名称,则无法避免反射。仅获取您知道需要的特定属性的值并在其他地方(例如在视图中)定义名称更有意义。但该设计选择取决于您。

于 2013-11-14T20:16:13.030 回答
0

看起来你正在尝试做一些与世界上RouteValueDictionary所做的非常相似的事情System.Web。您将无法绕过进行反射的需要,但您可能会从 Microsoft 如何通过查看其源代码来解决此问题中受益。

如果您创建了一个类似于他们的 Dictionary 类(比如“ DynamicDictionary”),那么您可以将您的方法更改为:

if (collection == null)
{
    return new List<Dictionary<string, object>>();
}
return collection.Select(e => new DynamicDictionary(e));

而且,当然,我建议让您的方法返回一个IDictionary(甚至是IReadOnlyDictionary接口,这样您就不会与特定的字典实现紧密耦合。

于 2013-11-14T20:06:45.700 回答
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)));
于 2013-11-14T21:01:07.090 回答