相关:Create a Lambda Expression With 3 conditions
请考虑此准则:
from a in myTbl
where a.Address.Contains(strToCheck)
select a
如何将其转换为表达式树并使用表达式编写上述代码?
主要问题是将a.Address.Contains(strToCheck)
转换为Expression Tree
。
修改1)地址是 string
字段,strToCheck
是 string
由于
答案 0 :(得分:2)
a.Address.Contains(strToCheck)
代表a.Address
实例上string.Contains
实例方法的调用 {{ 1}} 参数。
构建相应表达式的最简单方法是使用以下Expression.Call
overload:
strToCheck
像这样(使用链接问题中的术语):
public static MethodCallExpression Call(
Expression instance,
string methodName,
Type[] typeArguments,
params Expression[] arguments
)
答案 1 :(得分:0)
您没有指定myTbl的类型,
所以我只使用一个对象列表创建了一个简单的解决方案。
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Collections.Generic;
namespace Test
{
class Program
{
static void Main(string[] args) {
var adresses = FilterByAddress("Address", new List<Person> { new Person { Address = "Address1" }, new Person { Address = "AAAAAA" } });
}
public static IEnumerable<Person> FilterByAddress(string strToCheck, List<Person> list) {
var listParam = Expression.Parameter(typeof(IEnumerable<Person>), "list");
Expression<Func<Person, bool>> contains = a => a.Address.Contains(strToCheck);
var select = typeof(Enumerable).GetMethods().Single(m => m.Name.Equals("Where") && m.GetParameters()[1].ParameterType.GetGenericArguments().Length == 2);
var genericMethod = select.MakeGenericMethod(new[] { typeof(Person) });
var call = Expression.Call(null, genericMethod, new Expression[] { listParam, contains });
var lambda = Expression.Lambda<Func<IEnumerable<Person>, IEnumerable<Person>>>(call, new[] { listParam });
return lambda.Compile().Invoke(list);
}
}
public class Person
{
public string Address { get; set; }
}
}
如果您想按谓词使用过滤器,可以传递Expresssion<Func<Person, bool>>
作为参数(一行)
static void Main(string[] args) {
var strToCheck = "Address";
var list = new List<Person> { new Person { Address = "Address1" }, new Person { Address = "AAAAAA" } };
var adresses = FilterByAddress(list, p => p.Address.Contains(strToCheck));
}
public static IEnumerable<Person> FilterByAddress(List<Person> list, Expression<Func<Person, bool>> predicateEx) {
var listParam = Expression.Parameter(typeof(IEnumerable<Person>), "list");
var select = typeof(Enumerable).GetMethods().Single(m => m.Name.Equals("Where") && m.GetParameters()[1].ParameterType.GetGenericArguments().Length == 2);
var genericMethod = select.MakeGenericMethod(new[] { typeof(Person) });
var call = Expression.Call(null, genericMethod, new Expression[] { listParam, predicateEx });
var lambda = Expression.Lambda<Func<IEnumerable<Person>, IEnumerable<Person>>>(call, new[] { listParam });
return lambda.Compile().Invoke(list);
}
如果你有一个跨越多行的非常复杂的谓词(表达式树可以从一行lambda中计算),你可以使用一个技巧从谓词Func中构造一个表达式树,如下所示:
static void Main(string[] args) {
var strToCheck = "Address";
Func<Person, bool> predicate = p => {
return p.Address.Contains(strToCheck);
};
var list = new List<Person> { new Person { Address = "Address1" }, new Person { Address = "AAAAAA" } };
var adresses = FilterByAddress(list, predicate);
}
public static IEnumerable<Person> FilterByAddress(List<Person> list, Func<Person, bool> predicate) {
var listParam = Expression.Parameter(typeof(IEnumerable<Person>), "list");
Expression<Func<Person, bool>> predicateEx = p => predicate(p);
var select = typeof(Enumerable).GetMethods().Single(m => m.Name.Equals("Where") && m.GetParameters()[1].ParameterType.GetGenericArguments().Length == 2);
var genericMethod = select.MakeGenericMethod(new[] { typeof(Person) });
var call = Expression.Call(null, genericMethod, new Expression[] { listParam, predicateEx });
var lambda = Expression.Lambda<Func<IEnumerable<Person>, IEnumerable<Person>>>(call, new[] { listParam });
return lambda.Compile().Invoke(list);
}
使用通用方法按谓词过滤列表
static void Main(string[] args) {
var strToCheck = "Address";
Func<Person, bool> predicate = p => {
return p.Address.Contains(strToCheck);
};
var list = new List<Person> { new Person { Address = "Address1" }, new Person { Address = "AAAAAA" } };
var adresses = FilterBy<Person>(list, predicate);
}
public static IEnumerable<T> FilterBy<T>(List<T> list, Func<T, bool> predicate) {
var listParam = Expression.Parameter(typeof(IEnumerable<T>), "list");
Expression<Func<T, bool>> predicateEx = p => predicate(p);
var select = typeof(Enumerable).GetMethods().Single(m => m.Name.Equals("Where") && m.GetParameters()[1].ParameterType.GetGenericArguments().Length == 2);
var genericMethod = select.MakeGenericMethod(new[] { typeof(T) });
var call = Expression.Call(null, genericMethod, new Expression[] { listParam, predicateEx });
var lambda = Expression.Lambda<Func<IEnumerable<T>, IEnumerable<T>>>(call, new[] { listParam });
return lambda.Compile().Invoke(list);
}
}