使用 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;
}
首先尝试看看是否可以找到强类型解决方案(表达式/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; }
}
}