构建具有多个参数的表达式树
Build an Expression Tree with multiple parameters
我正在尝试创建一个可以接受多个 属性 名称和一个字符串值的方法,该值将用于研究拥有这些属性的实体
我想要一个通用方法来替换这个:
public static Client[] GetClientByInfo(string info)
{
return Context.Db.Clients.Where(c =>
c.LastName.Contains(info) ||
c.FirstName.Contains(info)).ToArray();
}
所以我尝试了这个:
public static T[] FindByText<T>(string text, string[] properties)
where T: class
{
return Context.Db.Set<T>().AsNoTracking().Where(PropertyEquals<T, string>(properties, text)).ToArray();
}
public static Expression<Func<TItem, bool>> PropertyEquals<TItem, TValue>(string[] properties, TValue value)
{
MethodInfo startWithMethod = typeof(string).GetMethod("StartsWith", BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(string) }, null);
ParameterExpression parameter = Expression.Parameter(typeof(TItem));
ConstantExpression constant = Expression.Constant(value, typeof(TValue));
MemberExpression[] members = new MemberExpression[properties.Length];
for (int i = 0; i < properties.Length; i++)
members[i] = Expression.Property(parameter, properties[i]);
MethodCallExpression callExp = Expression.Call(parameter, startWithMethod, members);
return Expression.Lambda<Func<TItem, bool>>(callExp, parameter);
}
我调用的时候出错了Expression.Call
是否可以构建这样的表达式,或者我必须使用连接表达式?
我不确定你想对每个参数做什么。假设所有字段都是 string
,并且您想针对每个字段调用 StartsWith
,这将起作用:
public static Expression<Func<TItem, bool>> PropertyEquals<TItem>(string[] properties, string value)
{
MethodInfo startWithMethod = typeof(string).GetMethod("StartsWith", BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(string) }, null);
ParameterExpression parameter = Expression.Parameter(typeof(TItem));
ConstantExpression constant = Expression.Constant(value);
MemberExpression[] members = new MemberExpression[properties.Length];
for (int i = 0; i < properties.Length; i++)
members[i] = Expression.Property(parameter, properties[i]);
Expression predicate = null;
foreach (var item in members)
{
MethodCallExpression callExp = Expression.Call(item, startWithMethod, constant);
predicate = predicate == null
? (Expression)callExp
: Expression.OrElse(predicate, callExp);
}
return Expression.Lambda<Func<TItem, bool>>(predicate, parameter);
}
我正在尝试创建一个可以接受多个 属性 名称和一个字符串值的方法,该值将用于研究拥有这些属性的实体
我想要一个通用方法来替换这个:
public static Client[] GetClientByInfo(string info)
{
return Context.Db.Clients.Where(c =>
c.LastName.Contains(info) ||
c.FirstName.Contains(info)).ToArray();
}
所以我尝试了这个:
public static T[] FindByText<T>(string text, string[] properties)
where T: class
{
return Context.Db.Set<T>().AsNoTracking().Where(PropertyEquals<T, string>(properties, text)).ToArray();
}
public static Expression<Func<TItem, bool>> PropertyEquals<TItem, TValue>(string[] properties, TValue value)
{
MethodInfo startWithMethod = typeof(string).GetMethod("StartsWith", BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(string) }, null);
ParameterExpression parameter = Expression.Parameter(typeof(TItem));
ConstantExpression constant = Expression.Constant(value, typeof(TValue));
MemberExpression[] members = new MemberExpression[properties.Length];
for (int i = 0; i < properties.Length; i++)
members[i] = Expression.Property(parameter, properties[i]);
MethodCallExpression callExp = Expression.Call(parameter, startWithMethod, members);
return Expression.Lambda<Func<TItem, bool>>(callExp, parameter);
}
我调用的时候出错了Expression.Call 是否可以构建这样的表达式,或者我必须使用连接表达式?
我不确定你想对每个参数做什么。假设所有字段都是 string
,并且您想针对每个字段调用 StartsWith
,这将起作用:
public static Expression<Func<TItem, bool>> PropertyEquals<TItem>(string[] properties, string value)
{
MethodInfo startWithMethod = typeof(string).GetMethod("StartsWith", BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(string) }, null);
ParameterExpression parameter = Expression.Parameter(typeof(TItem));
ConstantExpression constant = Expression.Constant(value);
MemberExpression[] members = new MemberExpression[properties.Length];
for (int i = 0; i < properties.Length; i++)
members[i] = Expression.Property(parameter, properties[i]);
Expression predicate = null;
foreach (var item in members)
{
MethodCallExpression callExp = Expression.Call(item, startWithMethod, constant);
predicate = predicate == null
? (Expression)callExp
: Expression.OrElse(predicate, callExp);
}
return Expression.Lambda<Func<TItem, bool>>(predicate, parameter);
}