LINQ动态分组
我有一个类列表的记录,因此用户可以选择按属性名称动态分组行。 例如MenuText
, RoleName
或ActionName
。 然后我必须执行分组,所以我需要一个通用方法来通过传递列名来处理分组。
示例:
public class Menu { public string MenuText {get;set;} public string RoleName {get;set;} public string ActionName {get;set;} } public class Menus { var list = new List
如果您不使用数据库,可以使用Reflection:
private static object GetPropertyValue(object obj, string propertyName) { return obj.GetType().GetProperty(propertyName).GetValue(obj, null); }
用作:
var grouped = enumeration.GroupBy(x => GetPropertyValue(x, columnName));
这是一个非常原始的解决方案,更好的方法应该是使用Dynamic LINQ :
var grouped = enumeration.GroupBy(columnName, selector);
编辑 动态 LINQ可能需要一些解释。 它不是技术,图书馆或全新的框架。 它只是一对(2000 LOC)助手方法的便捷名称,可以让您编写此类查询。 只需下载源代码 (如果您没有安装VS示例)并在代码中使用它们。
最简单的方法:
if(columnName == "MextText") { return list.GroupBy(x => x.MenuText); } if(columnName == "RoleName") { return list.GroupBy(x => x.RoleName); } if(columnName == "ActionName") { return list.GroupBy(x => x.ActionName); } return list.GroupBy(x => x.MenuText);
您也可以使用表达式树。
private static Expression> GetColumnName(string property) { var menu = Expression.Parameter(typeof(Menu), "menu"); var menuProperty = Expression.PropertyOrField(menu, property); var lambda = Expression.Lambda>(menuProperty, menu); return lambda; } return list.GroupBy(GetColumnName(columnName).Compile());
这将产生一个lambda menu => menu.
。
但是,在课程变得臃肿之前,并没有太大的差异。
以下方法适用于LINQ to Objects以及LINQ to EF / NHibernate等。
它创建一个表达式,该表达式对应于作为字符串传递的列/属性,并将该表达式传递给GroupBy
:
private static Expression> GetGroupKey(string property) { var parameter = Expression.Parameter(typeof(Menu)); var body = Expression.Property(parameter, property); return Expression.Lambda>(body, parameter); }
使用基于IQueryable
的数据源:
context.Menus.GroupBy(GetGroupKey(columnName));
使用基于IEnumerable
的数据源:
list.GroupBy(GetGroupKey(columnName).Compile());
BTW:你的方法的返回类型应该是IEnumerable
,因为IGrouping
已经意味着每个键可以有多个 Menu
实例。
我按照Adriano的建议用Dynamic Linq做了这个
public static IEnumerable> GroupByMany( this IEnumerable elements, params string[] groupSelectors) { var selectors = new List>(groupSelectors.Length); selectors.AddRange(groupSelectors.Select(selector => DynamicExpression.ParseLambda(typeof (TElement), typeof (object), selector)).Select(l => (Func) l.Compile())); return elements.GroupByMany(selectors.ToArray()); } public static IEnumerable> GroupByMany ( this IEnumerable elements, params Func[] groupSelectors) { if (groupSelectors.Length > 0) { Func selector = groupSelectors.First(); return elements.GroupBy(selector); } return null; }
您可以轻松地为任何模型实现解决方案,我刚刚将其设为通用解决方案。
public static Expression> GetColumnName(string property) { var menu = Expression.Parameter(typeof(TElement), "groupCol"); var menuProperty = Expression.PropertyOrField(menu, property); var lambda = Expression.Lambda>(menuProperty, menu); return lambda; }
所谓的如下
_unitOfWork.MenuRepository.Get().GroupBy(LinqExtensions.GetColumnName("MenuText").Compile());
非常感谢你的帮助。
上述就是C#学习教程:LINQ动态分组分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1042811.html