使用类属性对列表进行分组和拆分

本文关键字:拆分 列表 属性 | 更新日期: 2023-09-27 18:25:59

我有以下代码,我真的很想将其生成,这样我就不必根据字段调用相同的LINQ语句。

有没有一种方法可以将这个switch语句移到ItemViewModel中,并调用以检索一个通用属性来根据其字符串名称执行分组?

    private List<List<ItemViewModel>> SplitItemList(List<List<ItemViewModel>> ItemLists, 
        string groupingField)
    {
        var newItemLists = new List<List<ItemViewModel>>();
        foreach (var itemList in ItemLists)
        {
            var newList = new List<List<ItemViewModel>>();
            switch (groupingField)
            {
                case "problem_description":
                    newList = itemList
                        .GroupBy(a => a.ProblemDescription)
                        .Select(x => x.ToList())
                        .ToList();
                    break;
                case "sw_code":
                    newList = itemList
                        .GroupBy(a => a.SoftwareCode)
                        .Select(x => x.ToList())
                        .ToList();
                    break;
                case "hw_code":
                    newList = itemList
                        .GroupBy(a => a.HardwareCode)
                        .Select(x => x.ToList())
                        .ToList();
                    break;
                case "etc":
                    break;
                default:
                    break;
            }
            newItemLists.AddRange(newList);
        }
        return newItemLists;
    }

使用类属性对列表进行分组和拆分

在循环中,尝试动态创建lambda:

public static Func<TIn, TOut> CreateGetter<TIn, TOut>(string propertyName)
{
   var input = Expression.Parameter(typeof(TIn));
   var expression = Expression.Property(input, typeof(TIn).GetProperty(propertyName));
   return Expression.Lambda<Func<TIn, TOut>>(expression, input).Compile();
}

这样说吧:

        var list = new List<Tuple<string, string>>();
        var getter = DynamicLinq.CreateGetter<Tuple<string, string>, string>("Item1");
        var query = list.GroupBy(getter).Select(x => x.ToList());

不过,请确保"groupingField"是属性的确切名称,否则这将不起作用。

编辑时间:根据您的评论,我给出了一个与您的场景相关的自定义属性使用示例:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class FriendlyNameAttribute : Attribute
{
    public string FriendlyName { get; set; }
    public FriendlyNameAttribute(string friendlyName)
    {
        FriendlyName = friendlyName;
    }
}
public class ItemViewModel
{
    private static readonly IDictionary<string, string> PropertyMap;
    static ItemViewModel()
    {
        PropertyMap = new Dictionary<string, string>();
        var myType = typeof (ItemViewModel);
        foreach (var propertyInfo in myType.GetProperties(BindingFlags.Instance | BindingFlags.Public))
        {
            if (propertyInfo.GetGetMethod() != null)
            {
                var attr = propertyInfo.GetCustomAttribute<FriendlyNameAttribute>();
                if (attr == null)
                    continue;
                PropertyMap.Add(attr.FriendlyName, propertyInfo.Name);
            }
        }
    }
    public static string GetPropertyMap(string groupingField)
    {
        string propName;
        PropertyMap.TryGetValue(groupingField, out propName);
        return propName; //will return null in case map not found.
    }
    [FriendlyName("problem_description")]
    public string ProblemDescription { get; set; }
    public string OtherProperty { get; set; } // will not be in map
}

这样使用:

var x = ItemViewModel.GetPropertyMap("problem_description");