2016-10-21 89 views
0

我有幾個自動完成操作,其中之一列出如下。我沒有爲每個自動完成Where方法編寫不同的謂詞,而是創建了autoCompletePredicate。由於我有多個autocompletes我使用反射來獲取該特定自動完成所需的屬性,並在我的autoCompletePredicate中使用該屬性。使用表達式與Func

我有以下代碼工作正常。

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.Object的 的GetValue(System.Object的)’的方法,而這種方法不能將 轉換成商店表達。「

我看着下面post這使得絕對意義上的,但我不知道我該如何使用我的場景,例如(這是使用Reflection動態查找屬性)。

另外,我想知道什麼可以利用使用表達式VS Func鍵(特別是在我的情況)什麼

+0

提供商正試圖採取組合表達式增添了更大的靈活性表達式並從中創建SQL,在這種情況下不能使用它。你可以在Linq-to-Objects中執行這些表達式,但是它根本不清楚它應該做什麼。 –

+0

@DStanley我在我的問題開始時提供了一些解釋。請看看它是否有意義。 – programmerboy

回答

2

您試圖嘗試在字符串執行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(); 
} 

它是可以通過定義自定義擴展方法和使用以及/或

+0

感謝您的回答。它真的幫助我理解表達式樹。但是,我注意到您正在構建'Expression Tree'並將其作爲FUNC返回。如果我正在返回'FUNC',那麼寫表達式樹有什麼意義呢?還有一件事我作爲表達式返回了你的方法,但仍然有這個錯誤'LINQ to Entities does not recognized the method'Boolean Contains(System.String,System.String)'method,並且這個方法不能被轉換成一個存儲表達式.' – programmerboy

+1

關於第一個問題,請理解您創建的每個表達式樹仍然會將其編譯到Func中,以便在Linq to Entities代碼中使用它,因爲沒有API會直接採用表達式樹,只有IQueryable直接採用表達式樹。所以你可以從方法中返回表達式樹,但是仍然需要編譯爲'Func ',並且這是一次性過程,不是每次都編譯,因爲這會影響性能。表達式樹是不同的,因爲你告訴系統,您需要做什麼,而不是你需要怎麼做 –

+0

關於第二個問題,這是我工作的代碼版本,請確保您創建一個使用'StringExtensions'類的擴展方法,張貼在回答並且如果代碼中的任何標準字符串(默認情況下沒有Contains方法)都可以訪問它並給出正確的答案,那麼此代碼將起作用。包含不是字符串的集合,這是一種解決方法。 –

相關問題