2013-11-14 53 views
1

我知道我們可以使用.ToDictionary(t => t.Key,t => t.Value)將linq結果集轉換爲Dictionary集合,但我正在尋找更多的東西。我想給LINQ結果轉換爲IEnumerable<Dictionary<string, object>>和下面是我在尋找:將Linq結果轉換爲字典的最佳實踐

這裏是我的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

它看起來就像你正在試圖做的非常相似,RouteValueDictionary確實在System.Web世界的東西。你將無法繞過反思的需要,但你可能會從看到their source code看到微軟如何解決這個問題中受益。

如果你創建了類似他們的字典類(說「DynamicDictionary」),那麼你就可以改變你的方法:

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

,當然,我會建議讓你的方法返回一個IDictionary( 。甚至IReadOnlyDictionary接口,這樣你就不會緊耦合到一個特定的字典實現

+0

很好,它絕對有助於改善代碼,感謝您的幫助,不能將此標記爲低點答案。 – Binoy

+0

不幸的是TypeDescriptor在WP8中不可用 – Binoy

+0

我檢查了RouteValueDictionary的代碼,它在AddValues方法中使用TypeDescriptor,我試圖以相同的方式更新代碼,但發現WP8中不存在TypeDescriptor – Binoy

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#名稱,則無法避免反射。只有獲得您需要的特定屬性的值並在別處定義名稱(如在視圖中)才更有意義。但是這個設計選擇取決於你。

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)));