2016-05-04 44 views
0

我試圖建立一個CallExpression喜歡的Equals創建CallExpression:LINQ表達式 - >使用枚舉類型

f.Equals(s); 

其中,ftenum SType

所以,

var equalsMethod = typeof(SType).GetMethod("Equals", new[] { typeof(SType) }); 
ConstantExpression constantExpression = Expression.Constant(value, typeof(SType)); 
var newBody = Expression.Call(expr.Body, equalsMethod, constantExpression); 
return Expression.Lambda<Func<TEntity, bool>>(newBody, expr.Parameters); 

我不知道,但equalsMethodBoolean Equals(System.Object)而不是Boolean Equals(SType)

所以,當我想建立CallExpression淨告訴我,我不能使用SType類型的表達式的方法Boolean Equals(System.Object)System.Object類型的參數。

怎麼了?

回答

2

當你調用f.Equals(s)你真的這樣做:

f.Equals((object)s) 

...因爲EnumValueType不超載Equals。所以基本上你需要有一個轉換 - 你可以對Equals方法你打電話,也更加清晰:

var equalsMethod = typeof(object).GetMethod("Equals", new[] { typeof(object) }); 
var constant = Expression.Constant(value, typeof(SType)); 
var boxed = Expression.Convert(constant, typeof(object)); 
var newBody = Expression.Call(expr.Body, equalsMethod, boxed); 
return Expression.Lambda<Func<TEntity, bool>>(newBody, expr.Parameters); 

誠然,你很可能避免了單獨的步驟,只是:

var equalsMethod = typeof(object).GetMethod("Equals", new[] { typeof(object) }); 
// Let this do the boxing for you... 
var constant = Expression.Constant(value, typeof(object)); 
var newBody = Expression.Call(expr.Body, equalsMethod, constant); 
return Expression.Lambda<Func<TEntity, bool>>(newBody, expr.Parameters); 

我還沒有嘗試過,但我懷疑它會工作得很好。

2

Jon已經描述了你的代碼有什麼問題。但是,我不知道爲什麼你曾經費心創建MethodCallExpressionEquals方法,而現在只是說(當然,準確地說,做相等比較)特定的Expression.Equal方法:

return Expression.Lambda<Func<TEntity, bool>>(
    Expression.Equal(expr.Body, Expression.Constant(value)), 
    expr.Parameters); 
+1

注意'Expression.Equal '是調用'operator =='而不是'Equals'。如果表達式被編譯,它們不能保證是等價的,但強烈鼓勵它。如果表達式在EntityFramework/LinqToSql查詢中使用,則它們的翻譯方式相同。 – Johnbot