2013-08-01 78 views
3

我想創建拉姆達這樣的創建LambdaExpression包含外部變量

user => user.Address == address 

但不編一個,我想回到LambdaExpression

如果拉姆達採取恆定這樣

user => user.Age == 50 

然後我可以用這個方法

public static LambdaExpression PropertyEqual(Type tEntityType, string propertyName, object value) 
    { 
     // entity => entity.PropName == const 
     var itemParameter = Expression.Parameter(tEntityType, "entity"); 
     return Expression.Lambda 
     (
      Expression.Equal 
      (
       Expression.Property 
       (
        itemParameter, 
        propertyName 
       ), 
       Expression.Constant(value) // Tried to replace this with Expression.Parameter or Expression.Variable but no luck 
      ), 
      new[] { itemParameter } 
     ); 
    } 

如何使這個方法接受可變address來自範圍外面從lambda表達式?

var addressPropertyName = "Address"; 
var address = new Address() {...}; 
var q = Repo.GetQuery().Where(PropertyEqual(typeof(User), addressPropertyName, address)) 

編輯:澄清我的問題:如何建立正確的Expression生成第一拉姆達?

更新:因爲EF does not support non-scalar variable

我改變lambda來user => user.AddressId == addressId的建議here這是不可能的。它只是此事如何讓AddressId FK PropertyInfo從已知的導航屬性Address

回答

4

不能動態地生成一個變量閉包(你不能延長其上下文之外的變量的生命週期),因爲這是編譯器的把戲(用於重寫代碼做到這一點)。

如果你不想關閉,但你需要一個額外的參數,那麼你可以附加參數添加到表達式。

你可以

Expression<Func<string>> myExpr =() => address; 

現在你有一個在你的地址關閉的表達式。現在你只需要結合這兩個表達式。

你得方法更改爲:

public static LambdaExpression PropertyEqual<T>(Type tEntityType, string propertyName, Expression<Func<T>> getValue) 
{ 
    // entity => entity.PropName == const 
    var itemParameter = Expression.Parameter(tEntityType, "entity"); 
    return Expression.Lambda 
    (
     Expression.Equal 
     (
      Expression.Property 
      (
       itemParameter, 
       propertyName 
      ), 
      Expression.Invoke(getValue) // You could directly use getValue.Body instead of Expression.Invoke(getValue) 
     ), 
     new[] { itemParameter } 
    ); 
} 
+0

增加額外的參數將變成像'(用戶地址)=> user.Address == address',而不是'用戶=>用戶。地址== address'具有不同的返回式'表達>',而不是'表達>' – CallMeLaNN

+1

你不能得到一個「參考」給一個變量,並把它放在一個'表達'。 'TypedReference'和表達式樹不是「兼容的」。你可以做的是預先創建一個指向你的地址的表達式,然後組成這兩個表達式樹。閉包將由編譯器完成。 – xanatos

+0

對不起,如何結合兩個表達式並返回'LambdaExpression'? 'Expression.Lambda(...)'只接受一個'Expression'體。 – CallMeLaNN