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 inConstantExpressions
. - Closures and
this
are nevernull
. - Both are classes, not value types - you cannot capture a reference to
this
from a struct. That's quite fortunate, because tellingdefault(StructType).Method()
fromthis.Method()
would oth开发者_如何学Pythonerwise be impossible wheneverthis == 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 withCompilerGeneratedAttribute
- Closure names contain the string
DisplayClass
, anonymous types containAnonymousType
- Anonymous types are generic, closures are not.
- Closures are nested classes, anonymous types are not.
- Closure names contain the string
this
must be a normal type: notCompilerGenerated
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...
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
精彩评论