正在构建动态表达式树以筛选集合属性2
本文关键字:筛选 集合 属性 构建 动态 表达式 | 更新日期: 2023-09-27 17:57:58
也许这是一个重复的线程,但我会尝试一下,因为有一个微小的差异。
我正在尝试构建一个动态表达式来筛选集合属性。
代码:
public class TestEntity
{
public int ID { get; set; }
public string Name { get; set; }
public IEnumerable<string> Values { get; set; }
}
public class TestFilter
{
public TestFilter()
{
var itens = new List<TestEntity>();
itens.Add(new TestEntity { ID = 1, Name = "Test1", Values = new List<string> { "V1", "V2" } });
itens.Add(new TestEntity { ID = 2, Name = "Test2", Values = new List<string> { "V6", "V3" } });
itens.Add(new TestEntity { ID = 3, Name = "Test3", Values = new List<string> { "V4", "V5" } });
itens.Add(new TestEntity { ID = 4, Name = "Test4", Values = new List<string> { "V2", "V3" } });
itens = itens.Where(e => e.Values.Any(c => c.Equals("V2"))).ToList();
**//Result IDs: 1, 4**
}
}
上面的过滤器将为我提供ID1和4。
我想筛选集合"Values"中存在某个值的实体。
到目前为止,我已经尝试过这个线程,但没有意识到它是如何做到的。
任何帮助都是值得的。
因此,您正在寻找一个方法,该方法给定集合属性名称和值将生成类似e => e.Collection.Any(c => c == value)
的Where
谓词。
您可以使用以下扩展方法(希望代码是不言自明的):
public static class QueryableExtensions
{
public static IQueryable<T> WhereAnyEquals<T>(this IQueryable<T> source, string collectionName, object value)
{
var e = Expression.Parameter(typeof(T), "e");
var collection = Expression.PropertyOrField(e, collectionName);
var itemType = (collection.Type.IsIEnumerableT() ? collection.Type :
collection.Type.GetInterfaces().Single(IsIEnumerableT))
.GetGenericArguments()[0];
var c = Expression.Parameter(itemType, "c");
var itemPredicate = Expression.Lambda(
Expression.Equal(c, Expression.Constant(value)),
c);
var callAny = Expression.Call(
typeof(Enumerable), "Any", new Type[] { itemType },
collection, itemPredicate);
var predicate = Expression.Lambda<Func<T, bool>>(callAny, e);
return source.Where(predicate);
}
private static bool IsIEnumerableT(this Type type)
{
return type.IsInterface && type.IsConstructedGenericType &&
type.GetGenericTypeDefinition() == typeof(IEnumerable<>);
}
}
像这样:
itens = itens.AsQueryable().WhereAnyEquals("Values", "V2").ToList();
如果您逐步执行代码,变量predicate
将包含您所要求的表达式。