使用 LINQ 筛选泛型列表,使用属性名称作为字符串文本 - 使用动态

本文关键字:字符串 动态 文本 属性 筛选 LINQ 泛型 列表 使用 | 更新日期: 2023-09-27 18:35:33

我想知道这种方法是否可以做得更好。我需要在作为字符串传入的成员名称上过滤通用列表。我的想法是将泛型列表转换为动态列表,然后将 expandoObject 转换为字典并检查成员名称是否存在。最后,使用 JsonSerializer 将动态列表转换回泛型列表。您对更好的实施有什么想法?反射?动态 LINQ(Scott Guthrie 在 2008 年做了一些工作)?表达式树?

        public static IEnumerable<T> FilterListByStringPropertyName<T>(this IEnumerable<T> genericList, int? enumId, string enumFieldName)
    {
        if (string.IsNullOrEmpty(enumFieldName))
        {
            throw new NullReferenceException("FilterByEnum: enumFieldName cannot be empty");
        }
        if (enumId == null)
        {
            //skip method as no filtering needed
            return genericList;
        }
        if (genericList.Count() == 0)
        {
            return genericList;
        }
        List<T> @return = new List<T>();
        List<dynamic> dynamicList = new List<dynamic>();
        //fill the dynamic list from generic list
        foreach (var genericItem in genericList)
            dynamicList.Add(genericItem.ToDynamic());
        var first = dynamicList.FirstOrDefault();
        //initialise filteredDynamicList
        IEnumerable<dynamic> filteredDynamicList = dynamicList;
        if (enumId != null)
        {
            //ExpandoObject implements IDictionary<string, object>, so cast as that to check what the fields are
            if (!((IDictionary<string, object>)first).ContainsKey(enumFieldName))
            {
                throw new KeyNotFoundException(string.Format("{0} is not a member of {1}", enumFieldName, genericList.GetType().GetGenericArguments()[0]));
            }
            //filter by the AddressStatus enum (as int)
            filteredDynamicList = dynamicList.Where(a => (int)((IDictionary<string, object>)a)[enumFieldName] == enumId.Value);
        }
        //convert from dynamic back to to generic
        var json = Newtonsoft.Json.JsonConvert.SerializeObject(filteredDynamicList);
        @return = Newtonsoft.Json.JsonConvert.DeserializeObject<List<T>>(json);
        return @return;
    }

使用 LINQ 筛选泛型列表,使用属性名称作为字符串文本 - 使用动态

首先尝试看看是否可以找到强类型解决方案(表达式/Func),然后尝试其他方法(反射)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace ConsoleApplication9
{
class Program
{
    static void Main(string[] args)
    {
        var customers = Enumerable.Range(1, 10).Select(c => new Customer() { Id = c, Name = "Customer " + c });
        var filteredCustomers = StronglyNameFilter(customers, c => c.Id == 1);
        var filteredCustomers2 = StronglyNameFilter(customers, c => c.Name == "Customer 1");
        var filteredCustomers3 = ReflectionFilter(customers, "Id", 1);
        var filteredCustomers4 = ReflectionFilter(customers, "Name", "Customer 1");
        Console.ReadLine();
    }
    private static IEnumerable<T> StronglyNameFilter<T>(IEnumerable<T> collection, Func<T, bool> filter)
    {
        return collection.Where(filter).ToList();
    }
    private static IEnumerable<T> ReflectionFilter<T>(IEnumerable<T> collection, string property, object value)
    {
        if (collection.Count() == 0)
            return new List<T>();
        PropertyInfo pInfo = collection.First().GetType().GetProperty(property);
        return collection.Where(c => object.Equals(pInfo.GetValue(c), value)).ToList();
    }
}
public class Customer
{
    public string Name { get; set; }
    public int Id { get; set; }
}
}