hazzik / DelegateDecompiler

A library which is able to decompile a delegate or a method body to its lambda representation
MIT License
526 stars 62 forks source link

Decompile for anonymous functions with variables from outer scope creates wrong expression #95

Closed morgen2009 closed 7 years ago

morgen2009 commented 7 years ago

If an anonymous function Expression<Func<...>> uses variables from outer scope, its expression tree would contain MemberExpression applied to the instance of anonymous class. This instance is presented by ConstantExpression and contains current variable values. The IL code references it as first parameter with OpCodes.Ldarg_0 code. In the same manner, the methods would reference the instance of their class.

The Decompile generates for both cases an expression with $this as first parameter, while for anonymous function $this should be replaced by current instance of function scope class.

The following test fails

[Test]
public void ShouldBeAbleToDecompileObjectInitializerWithOuterVariables()
{
    var date = DateTime.Now;
    Expression<Func<DateTime, TestClass>> expression = (x) => new TestClass { StartDate = date };
    Func<DateTime, TestClass> compiled = (x) => new TestClass { StartDate = date };
    Test(expression, compiled);
}

Because the body of expression is

new TestClass() {StartDate = value(DelegateDecompiler.Tests.DecompileExtensionsTests+<>c__DisplayClass37_0).date}

while the body of decompiled expression is

new TestClass() {StartDate = this.date}

I don’t know either this is technically possible to inject in decompiled expression tree the current value of DelegateDecompiler.Tests.DecompileExtensionsTests+<>c__DisplayClass37_0.

Related to #83

hazzik commented 7 years ago

Released 0.22.0