在C#中创建通用的表达式生成方法

4

我正在使用多种方法构建IQueryable查询。这些方法有些复杂,但我想解决的问题可以提炼并简化为以下形式。我有两个方法:

private Expression<Func<T, bool>> CreateExpressionA(string ValueA)
{
  return a => a.PropertyA.ToLower() == ValueA;
}

private Expression<Func<T, bool>> CreateExpressionB(string ValueB)
{
  return a => a.PropertyB.ToLower() == ValueB;
}

我更希望有这个:

private Expression<Func<T, bool>> CreateExpression(??? Selector, string Value)
{
  return a => a.Selector.ToLower() == Value;
}

或者采用类似的方法,使我避免有两个完全相同的方法,唯一的区别在于使用对象的哪个属性。
有没有一种优雅的方式可以做到这一点?

1
我想使用反射应该很容易... - Zohar Peled
这肯定是正确的(就我在答案中看到的而言),只是我不知道怎么写。但我更喜欢无反射的答案。 - Wapac
3个回答

4

您可以传递一个选择器 Func,它返回一个 string 属性:

private Expression<Func<T, bool>> CreateExpression<T>(Func<T, string> selector, string value)
{
    return a => selector(a).ToLower() == value;
}

使用方法:

CreateExpression<MyType>(x => x.PropertyA, "thevalue");

我喜欢这个解决方案。这正是我在寻找的,而且它运行良好。谢谢! - Wapac

1

您可以使用反射,更准确地说是作为参数的 PropertyInfo 类,但实现会更加复杂。该方法可以按如下方式实现。

private Expression<Func<T, bool>> CreateExpression(PropertyInfo iInfo, string Value)
{
    return a => (iInfo.GetPropertyValue(a) as string).ToLower() == ValueB;
}

然而,请注意,这仅适用于属性的类型为string的情况,否则可以使用额外的类型参数。

0
你可以从头开始创建表达式:
private Expression<Func<T, bool>> CreateExpression(string propertyName, string value) {
    ParameterExpression param = Expression.Parameter(typeof(T));
    MemberExpression property = Expression.Property(param, propertyName);
    var valExpr = Expression.Constant(value);
    var body = Expression.Equal(property, valExpr);
    return Expression.Lambda<Func<T, bool>>(body, param);
}

调用:

var expression = CreateExpression<TypeOfA>("PropertyA", "ValueForPropertyA");

这有点凭空想象,但我认为这至少可以让你开始。如果需要帮助,请告诉我。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接