I want this test to pass:
[Test]
public void LambdaTest()
{
var m = Expression.Lambda(typeof(Func<int>), Expression.Constant(0)).Compile();
Assert.That(m.Method.DeclaringType, Is.Not.Null);
}
This is necessary to make stack-walking lagacy code to work correctly. What's the simpliest way to do it?
I would prefer the most portable way.
You can build a new type at runtime and then compile the expression into a method of that type.
You need to create a new assembly and a new module at run time. Once you create those, you can use them to create as many types as you like. Here is a code sample to create the assembly and the module:
var assemblyBuilder =
AppDomain.CurrentDomain.DefineDynamicAssembly(
new AssemblyName {Name = "MyNewAssembly"},
AssemblyBuilderAccess.Run);
var moduleBuilder = assemblyBuilder.DefineDynamicModule("MyNewModule");
Now, you can use the module builder to define a new type like this:
var typeBuilder = moduleBuilder.DefineType("MyNewType");
And then a new method like this:
var methodBuilder =
typeBuilder.DefineMethod(
"MyNewMethod",
MethodAttributes.Public | MethodAttributes.Static,
typeof(int), //returns an int
new Type[]{}); //takes no parameters
Please note that the method signature should match your expression delegate type.
Next, we compile the expression into the new method using the CompileToMethod
method:
var expression = Expression.Lambda(typeof(Func<int>), Expression.Constant(0));
expression.CompileToMethod(methodBuilder);
We generate the actual type from the type builder:
var type = typeBuilder.CreateType();
Then we use the Delegate.CreateDelegate
method to create a delegate to the newly created static method like this:
Func<int> func =
(Func<int>)Delegate.CreateDelegate(
typeof(Func<int>),
type.GetMethod("MyNewMethod"));
int value = func(); //Test
Now func.Method.DeclaringType
would return our dynamically created type.
You can easily use this code to generate some helper methods to make it easy to use.