简体   繁体   English

使用Expression vs Func

[英]Using Expression vs Func

I have several autocomplete actions, one of them is listed below. 我有几个自动完成操作,下面列出了其中之一。 Instead of writing different predicates for each autocomplete Where method, I have created an autoCompletePredicate . 我没有为每个自动完成Where方法编写不同的谓词,而是创建了一个autoCompletePredicate Since I have multiple autocompletes I am using Reflection to get the Property which is required for that specific AutoComplete and use that Property in my autoCompletePredicate . 由于我有多个自动完成功能,因此我在使用Reflection获取该特定AutoComplete所需的属性,并在我的autoCompletePredicate使用该属性。

I have following code which is working alright. 我有下面的代码,可以正常工作。

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;
};

How can I change this code into Expression. 如何将这段代码更改为Expression。 I tried below code which compiled fine but at runtime I got the following error 我尝试下面的代码编译良好,但在运行时出现以下错误

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 to Entities does not recognize the method 'System.Object GetValue(System.Object)' method, and this method cannot be translated into a store expression." “ LINQ to Entities无法识别方法'System.Object GetValue(System.Object)',并且该方法无法转换为商店表达式。”

I looked at the following post which makes absolute sense, but I am not sure how I can use that example in my scenario (which is dynamically finding properties using Reflection ). 我看了下面的文章 ,这绝对有道理,但是我不确定如何在我的场景中使用该示例(该示例使用Reflection动态查找属性)。

Also, what I would like to know what can be advantage of using Expression vs Func (specially in my case) 另外,我想知道使用Expression vs Func有什么好处(特别是在我的情况下)

You are trying to trying to execute Contains method on string and want that to be represented in the ExpressionTrees , following is the code you need: 您试图在字符串上执行Contains方法,并希望在ExpressionTrees表示该方法,以下是您需要的代码:

Create String Extension method - Contains: (Case Insensitive) 创建字符串扩展方法-包含:(不区分大小写)

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

Create the AutoCompleteExpression method as follows, it returns Func<MyObject, bool> : 如下创建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();
 }

It is possible to add lot more flexibility by defining custom extension methods and combining expressions using And / Or 通过定义自定义扩展方法并使用And / Or组合表达式,可以增加更多的灵活性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM