2013-08-01 52 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