C# List实现行转列的通用方案

2019-12-30 16:48:30于丽

 

 

区域月份-户明细报表
区域 月份 张三 李四
燃气费 电费 水费 燃气费 电费 水费
江夏区 2016-01 2240.9 330 425 5167 264.5 177.9
洪山区 2016-01 576.7 264.7 173.2 665.2 108.9 184.9
江夏区 2016-02 3240.9 430 525 6167 364.5 277.9
洪山区 2016-02 676.7 364.7 273.2 765.2 208.9 284.9

 

现在后台查出来的数据是List<House>类型,前台传过来分组维度和动态列字段。

第1个表格前台传给后台参数

{DimensionList:['Name'],DynamicColumn:'Month'}

 第2个表格前台传给后台参数

{DimensionList:['Area'],DynamicColumn:'Month'}

第3个表格前台传给后台参数

{DimensionList:['Area','Month'],DynamicColumn:'Name'}

问题描述清楚后,仔细分析后你就会发现这里的难题在于动态分组,也就是怎么根据前台传过来的多个维度对List进行分组。

动态Linq

下面使用System.Linq.Dynamic完成行转列功能,Nuget上搜索System.Linq.Dynamic即可下载该包。

代码进行了封装,实现了通用的List<T>行转列功能。


/// <summary>
 /// 动态Linq方式实现行转列
 /// </summary>
 /// <param name="list">数据</param>
 /// <param name="DimensionList">维度列</param>
 /// <param name="DynamicColumn">动态列</param>
 /// <returns>行转列后数据</returns>
 private static List<dynamic> DynamicLinq<T>(List<T> list, List<string> DimensionList, string DynamicColumn, out List<string> AllDynamicColumn) where T : class
 {
 //获取所有动态列
 var columnGroup = list.GroupBy(DynamicColumn, "new(it as Vm)") as IEnumerable<IGrouping<dynamic, dynamic>>;
 List<string> AllColumnList = new List<string>();
 foreach (var item in columnGroup)
 {
 if (!string.IsNullOrEmpty(item.Key))
 {
  AllColumnList.Add(item.Key);
 }
 }
 AllDynamicColumn = AllColumnList;
 var dictFunc = new Dictionary<string, Func<T, bool>>();
 foreach (var column in AllColumnList)
 {
 var func = DynamicExpression.ParseLambda<T, bool>(string.Format("{0}=="{1}"", DynamicColumn, column)).Compile();
 dictFunc[column] = func;
 }
 //获取实体所有属性
 Dictionary<string, PropertyInfo> PropertyInfoDict = new Dictionary<string, PropertyInfo>();
 Type type = typeof(T);
 var propertyInfos = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
 //数值列
 List<string> AllNumberField = new List<string>();
 foreach (var item in propertyInfos)
 {
 PropertyInfoDict[item.Name] = item;
 if (item.PropertyType == typeof(int) || item.PropertyType == typeof(double) || item.PropertyType == typeof(float))
 {
  AllNumberField.Add(item.Name);
 }
 }
 //分组
 var dataGroup = list.GroupBy(string.Format("new ({0})", string.Join(",", DimensionList)), "new(it as Vm)") as IEnumerable<IGrouping<dynamic, dynamic>>;
 List<dynamic> listResult = new List<dynamic>();
 IDictionary<string, object> itemObj = null;
 T vm2 = default(T);
 foreach (var group in dataGroup)
 {
 itemObj = new ExpandoObject();
 var listVm = group.Select(e => e.Vm as T).ToList();
 //维度列赋值
 vm2 = listVm.FirstOrDefault();
 foreach (var key in DimensionList)
 {
  itemObj[key] = PropertyInfoDict[key].GetValue(vm2);
 }
 foreach (var column in AllColumnList)
 {
  vm2 = listVm.FirstOrDefault(dictFunc[column]);
  if (vm2 != null)
  {
  foreach (string name in AllNumberField)
  {
  itemObj[name + column] = PropertyInfoDict[name].GetValue(vm2);
  }
  }
 }
 listResult.Add(itemObj);
 }
 return listResult;
 }