使用表达式和函数

本文关键字:函数 表达式 | 更新日期: 2023-09-27 18:14:09

我有几个自动完成操作,其中一个列在下面。我没有为每个自动完成的Where方法编写不同的谓词,而是创建了一个autoCompletePredicate。由于我有多个自动完成,我使用反射来获得该特定自动完成所需的属性,并在我的autoCompletePredicate中使用该属性。

我有下面的代码是正常工作的。

static string param1, param2;
static PropertyInfo[] properties;
static PropertyInfo prop1, prop2;
public IHttpActionResult GetAutComplete(string term, string dependent)
{
    int pagerSize = 10;
    properties = new MyObject().GetType().GetProperties();
    prop1 = properties.Where(p => p.Name.ToUpper().Equals("PROP1")).FirstOrDefault();
    prop2 = properties.Where(p => p.Name.ToUpper().Equals("PROP2")).FirstOrDefault();
    param1 = term;
    param2 = dependent;
    return Json(context.MyObject.Where(autoCompletePredicate).Select(r => new { label = r.PROP1 }).Distinct().OrderBy(r => r.label).Take(pagerSize).ToList());
}
Func<MyObject, int, bool> autoCompletePredicate = (GF, index) =>
{
    bool isFound = false;
    string term, dependent;
    term = prop1.GetValue(GF).ToString();
    dependent = prop2.GetValue(GF).ToString();
    var termFound = term.Contains(param1.ToUpper());
    var dependentFound = String.IsNullOrEmpty(param2) ? true : dependent.Contains(param2.ToUpper());
    isFound = termFound && dependentFound;
    return isFound;
};

如何将此代码更改为表达式。我尝试下面的代码编译良好,但在运行时,我得到以下错误

public static Expression<Func<MyObject, bool>> AutoCompleteExpression()
{
    return r => prop1.GetValue(r).ToString().Contains(param1.ToUpper()) && (String.IsNullOrEmpty(param2) ? true : prop2.GetValue(r).ToString().Contains(param2.ToUpper()));
}

"LINQ到实体无法识别方法'System '。对象GetValue(System.Object)'方法,该方法不能被翻译转换成存储表达式。"

我看了下面的帖子,这是绝对有意义的,但我不确定我如何在我的场景中使用这个例子(这是动态地使用 Reflection 查找属性)。

此外,我想知道使用表达式与函数的优势(特别是在我的情况下)

使用表达式和函数

您正在尝试尝试在字符串上执行Contains方法,并希望在ExpressionTrees中表示,以下是您需要的代码:

创建字符串扩展方法-包含:(不区分大小写)

public static class StringExtensions
{
    public static bool Contains(this string source, string toCheck)
    {
        return source.IndexOf(toCheck, StringComparison.OrdinalIgnoreCase) >= 0;
    }
}

按如下方式创建AutoCompleteExpression方法,它返回Func<MyObject, bool>:

public static Func<MyObject, bool> AutoCompleteExpression()
{
   // Create ParameterExpression
   ParameterExpression parameterType = Expression.Parameter(typeof(MyObject), "object");
   // Create MemberExpression for Columns
   MemberExpression typeColumnProp1 = Expression.Property(parameterType, "PROP1");
   MemberExpression typeColumnProp2 = Expression.Property(parameterType, "PROP2");
   // Create MethoIndo
   MethodInfo containsMethodInfo = typeof(StringExtensions).GetMethod("Contains",new[] { typeof(string), typeof(string) },null);    
   // Create ConstantExpression values
   ConstantExpression constant1 = Expression.Constant(param1, typeof(string));
   ConstantExpression constant2 = Expression.Constant(param2, typeof(string));
   // Expression for calling methods
   MethodCallExpression expression1 = Expression.Call(null, containsMethodInfo, typeColumnProp1, constant1);
   MethodCallExpression expression2 = Expression.Call(null, containsMethodInfo, typeColumnProp2, constant2);
   // Combine `MethodCallExpression` to create Binary Expression
   BinaryExpression resultExpression = Expression.And(expression1,expression2);
    // Compile Expression tree to fetch `Func<MyObject, bool>`
   return Expression.Lambda<Func<MyObject, bool>>(resultExpression, parameterType).Compile();
 }

可以通过定义自定义扩展方法和使用and/Or组合表达式来增加更多的灵活性