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

时间:2014-10-08 11:18:39

标签: c# linq grouping

我有以下代码,我真的想要通用,所以我不必调用依赖于该字段的相同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;
    }

1 个答案:

答案 0 :(得分:0)

在循环中,尝试动态创建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());

确保&#34; groupingField&#34;是该物业的确切名称,否则这不会起作用。

EDITED :: 根据您的评论,我将举例说明与您的方案相关的自定义属性用法:

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