Access the value of a member expression

前端 未结 9 2019
滥情空心
滥情空心 2020-12-04 08:33

If i have a product.

var p = new Product { Price = 30 };

and i have the following linq query.

var q = repo.Products().Where         


        
相关标签:
9条回答
  • 2020-12-04 09:12

    The constant expression is going to point to a capture-class generated by the compiler. I've not included the decision points etc, but here's how to get 30 from that:

    var p = new Product { Price = 30 };
    Expression<Func<Product, bool>> predicate = x => x.Price == p.Price;
    BinaryExpression eq = (BinaryExpression)predicate.Body;
    MemberExpression productToPrice = (MemberExpression)eq.Right;
    MemberExpression captureToProduct = (MemberExpression)productToPrice.Expression;
    ConstantExpression captureConst = (ConstantExpression)captureToProduct.Expression;
    object product = ((FieldInfo)captureToProduct.Member).GetValue(captureConst.Value);
    object price = ((PropertyInfo)productToPrice.Member).GetValue(product, null);
    

    price is now 30. Note that I'm assuming that Price is a property, but in reality you would write a GetValue method that handles property / field.

    0 讨论(0)
  • 2020-12-04 09:13

    Using Expression.Lambda(myParameterlessExpression).Compile().Invoke() has several drawbacks:

    • .Compile() is slow. It can take multiple milliseconds to complete even for small expression fragments. The Invoke-call is super-fast afterwards though, takes only few nanoseconds for simple arithmetic expressions or member accesses.
    • .Compile() will generate (emit) MSIL code. That might sound perfect (and explains the excellent execution speed) but the problem is: That code takes up memory, which can not be freed before the application finishes, even when the GC collected the delegate-reference!

    One can either avoid Compile() altogether to avoid these issues or cache the compiled delegates for re-using them. This little library of mine offers both interpretation of Expressions as well as cached compilation, where all constants and closures of the expression get replaced by additional parameters automatically, which are then re-inserted in a closure, which is returned to the user. Both processes are well-tested, used in production, both have their pros and cons against each other but are well over 100x faster than Compile() - and avoid the memory leak!

    0 讨论(0)
  • 2020-12-04 09:17

    And what exactly are you trying to accomplish?

    Because to access the value of Price, you'd have to do something like:

    var valueOfPrice = q[0].Price;
    
    0 讨论(0)
提交回复
热议问题