Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Heuristic for "this" and closures OK? (Expression trees)

Consider the following Expression:

class A {
    int x;
    public void Method(int y) {
        Expression<Func<bool>> expr=() => x == y;
        //...

Here, the expression involves an automatically created closure for y, and a reference to this of type A for the (implicit) this.x. Both will be represented as a MemberExpression on a ConstantExpression in the expression tree. Given an expression such as expr or a more complicated expression with a this reference and/or a closure, I want identify that a particular ConstantExpression is actually "this" or an implicitly constructed closure to be able to regenerate C# from an expression tree (ExpressionToCode).

I built a "solution" using some heuristics since there doesn't seem to be a perfect solution.

  • Closures and this in lambda's are always in ConstantExpressions.
  • Closures and this are never null.
  • Both are classes, not value types - you cannot capture a reference to this from a struct. That's quite fortunate, because telling default(StructType).Method() from this.Method() would otherwise be impossible whenever this == default(StructType).
  • Builtin types (string, Enums, decimal, Type, all primitives) are actually real constants, not this or a closure
  • Closures and Anonymous types start with < and are annotated with CompilerGeneratedAttribute
    • Closure names contain the string DisplayClass, anonymous types contain AnonymousType
    • Anonymous types are generic, closures are not.
    • Closures are nested classes, anonymous types are not.
  • this must be a normal type: not CompilerGenerated and does not start with <

Are the above heuristics sufficient to distinguish between real constants, this, closures and anonymous types? I.e. are there cases where these heuristics fail, or am I missing any? Is this likely to break in future .NET versions?

Edit: I first asked this question in an open-ended fashion, without result; I rewrote the question to include what I've come up so far. Any suggestions much appreciated - the bounty's expiring tomorrow, any idea at all is welcome...

like image 725
Eamon Nerbonne Avatar asked Jan 18 '11 09:01

Eamon Nerbonne


1 Answers

Ok, I manage to find about the A Type from the expression:

class Program
{
    class A
    {
        int x;
        public Expression<Func<bool>> Method(int y)
        {
            Expression<Func<bool>> expr = () => x == y;
            return expr;
        }
    }

    static void Main(string[] args)
    {
        var expr = new A().Method(10);

        dynamic body = expr.Body;

        A instance = body.Left.Expression.Value;

        Console.Write(instance.ToString());

        Console.ReadKey();
    }
 }

The dynamic is just to go fast.

edit 2: got it

like image 119
Guillaume86 Avatar answered Nov 15 '22 07:11

Guillaume86