Creating a method with Reflection.Emit, and then invoking it - c#

This sounds like such an obvious thing but I am having a lot of difficulty. Basically, what I'm doing is generating a method using Reflection.Emit and I then want to call it. So far, I have the method building and such, but I can't get a reference to the method after it's built because "The invoked member is not supported before the type is created."
Here is what I basically do:
AssemblyBuilder assembly;
ModuleBuilder module;
TypeBuilder containerTypeBuilder;
Type containerType;
var name = new AssemblyName();
name.Name = "DynamicWrapper";
var domain = Thread.GetDomain();
assembly = domain.DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndSave);
module = assembly.DefineDynamicModule(assembly.GetName().Name, false);
containerTypeBuilder = module.DefineType("__DynamicWrapperType",
TypeAttributes.Public | TypeAttributes.Class |
TypeAttributes.AutoClass |
TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit |
TypeAttributes.AutoLayout, typeof(object));
//build method
var mb = containerTypeBuilder.DefineMethod("generatedmethod" + (unique++),
MethodAttributes.Public | MethodAttributes.Static, typeof (int),
new Type[] {});
//build method body and all that
.....
var type=module.GetType("__DynamicWrapperType");
var info=type.GetMethod(mb.Name, BindingFlags.Static | BindingFlags.Public); //error here
How do I take my freshly built method and load it up so that I can invoke it?
Also, I've tried mb.Invoke, but that yields "The invoked member is not supported in a dynamic module."

If you are creating individual method(s), then DynamicMethod is a much better choice (especially since your method is static) - you just useCreateDelegate (specifying the delegate type), cast to that delegate, and invoke. It is also less overhead, and collectible.
But if you are forced to use MethodBuilder: you must use CreateType on the TypeBuilder, then use reflection on the now real type (returned from CreateType).

Related

C# Getting a previously defined method builder from the type builder

Consider the following C# code:
var methodBuilder1 = typeBuilder.DefineMethod("GetMedalIds", MethodAttributes.Public | MethodAttributes.HideBySig, CallingConventions.HasThis, typeof(int[]), null);
var methodBuilder2 = typeBuilder.DefineMethod("GetMedalIds", MethodAttributes.Public | MethodAttributes.HideBySig, CallingConventions.HasThis, typeof(int[]), null);
First, note that the arguments into DefineMethod are identical (and arbitrary), and typeBuilder is the same instance in both cases. With this in mind, I have discovered the methodBuilder1 and methodBuilder2 both point to the same instance (at least methodBuiilder1 == methodBuilder2 is always true), leading me to assume that if the method builder hasn't already been defined, type builder defines it, otherwise it returns the already defined method builder.
My question is this: The comments on DefineMethod(...) says nothing about the above, so are my assumptions GUARANTEED to always be true as far as the C# specification is concerned, or is it an implementation detail that is subject to change? .
Assumptions in the question are incorrect. The instances are logically equivalent (== returns true), but point to separate instances. You can test this with Object.ReferenceEquals(...).
Use this answer for dotnet core 3.1:
using System;
using System.Reflection;
using System.Reflection.Emit;
namespace MethodBuilderDemo
{
class Program
{
static void Main(string[] args)
{
AssemblyName asmName = new AssemblyName("DemoMethodBuilder1");
AssemblyBuilder demoAssembly = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(Guid.NewGuid().ToString()), AssemblyBuilderAccess.Run);
ModuleBuilder demoModule = demoAssembly.DefineDynamicModule(asmName.Name);
TypeBuilder demoType = demoModule.DefineType("DemoType",TypeAttributes.Public | TypeAttributes.Abstract);
var methodBuilder1 = demoType.DefineMethod("GetMedalIds", MethodAttributes.Public | MethodAttributes.HideBySig, CallingConventions.HasThis, typeof(int[]), null);
var methodBuilder2 = demoType.DefineMethod("GetMedalIds", MethodAttributes.Public | MethodAttributes.HideBySig, CallingConventions.HasThis, typeof(int[]), null);
Console.WriteLine($"==: {methodBuilder1 == methodBuilder2}");
Console.WriteLine($"ref equals: {Object.ReferenceEquals(methodBuilder1, methodBuilder2)}");
}
}
}
gives
==: True
ref equals: False

How to attach Expression.Lambda to ANY owner type?

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.
Ok, I found it myself but I'm not sure how it will work in .NET Core and which framework may or may not support this. If you have a better (more elegant or portable) solution please feel free to post your answer.
The key is to use CompileToMethod of Lambda expression.
[Test]
public void LambdaTest2()
{
var asm = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("test"), AssemblyBuilderAccess.Run);
var masm = asm.DefineDynamicModule("main");
var type = masm.DefineType("TestType");
var mb = type.DefineMethod("TestMethod", MethodAttributes.Public | MethodAttributes.Static, typeof(int), new Type[0]);
// your lambda
ConstantExpression expressionTree = Expression.Constant(0);
Expression.Lambda(typeof(Func<int>), expressionTree).CompileToMethod(mb);
var m = (Func<int>)Delegate.CreateDelegate(typeof(Func<int>), type.CreateType().GetMethod("TestMethod"));
Assert.That(m.Method.DeclaringType, Is.Not.Null);
// you can create another in the same module but with another type (because type can't be changed)
var type2 = masm.DefineType("TestType2");
var mb2 = type2.DefineMethod("TestMethod2", MethodAttributes.Public | MethodAttributes.Static, typeof(int), new Type[0]);
// your lambda 2
ConstantExpression expresisonTree2 = Expression.Constant(1);
Expression.Lambda(typeof(Func<int>), expresisonTree2).CompileToMethod(mb2);
var m2 = (Func<int>)Delegate.CreateDelegate(typeof(Func<int>), type2.CreateType().GetMethod("TestMethod2"));
Assert.That(m2.Method.DeclaringType, Is.Not.Null);
// check correctness
Assert.That(m(), Is.EqualTo(0));
Assert.That(m2(), Is.EqualTo(1));
}
A lambda expression compiles to a DynamicMethod, which is always null for the DeclaringType property.
See DynamicMethod definition
See this SO answer also
Would make my life easier as well if I could find a way around that.

Generate code for generic nested class with Reflection.Emit

I'm trying to generate code using Reflection.Emit which would look identical or similar to what C# compiler generates for this:
public interface Function<in T, out Res>
{
Res Apply(T p);
}
public class MyMain<A>
{
class Closure : Function<A, A>
{
public A Apply(A p)
{
throw new NotImplementedException();
}
}
}
My code works fine if I use some real type, but when I replace it with generic, I get BadImageFormatException.
private static void CreateGenericClosures()
{
AssemblyName assemblyName = new AssemblyName("genericClosure");
AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Save);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name, assemblyName.Name + ".dll");
TypeBuilder main = moduleBuilder.DefineType("Main", TypeAttributes.Class | TypeAttributes.Public);
Type t = typeof (Foo);
// Defining generic param for Main class
GenericTypeParameterBuilder[] generics = main.DefineGenericParameters("A");
// t = generics[0]; // [1] Uncomment to enable for nested class
var iFunctionType = typeof (Function<,>).MakeGenericType(t, t);
TypeBuilder closure = main.DefineNestedType("Closure", TypeAttributes.Class | TypeAttributes.NestedPrivate, typeof (object));
closure.AddInterfaceImplementation(iFunctionType);
MethodBuilder applyMethod = closure.DefineMethod("Apply",
MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.Public,
CallingConventions.Standard);
applyMethod.SetParameters(t);
applyMethod.SetReturnType(t);
ILGenerator body = applyMethod.GetILGenerator();
body.Emit(OpCodes.Ldnull);
body.Emit(OpCodes.Ret);
closure.DefineDefaultConstructor(MethodAttributes.Public);
closure.CreateType();
main.CreateType();
assemblyBuilder.Save(assemblyName.Name + ".dll", PortableExecutableKinds.Required32Bit, ImageFileMachine.I386);
}
Uncomment [1] to see the exception.
Any ideas what could be wrong?
It turns out that nested classes don't actually have access to their parents' generic type parameters/arguments and to be well-formed they actually need to redeclare all of the generic type parameters of their parents (see e.g. this old blog post, or section I.10.7.1 of the ECMA CLI spec, which goes into lots of detail about the requirements for CLS compatibility). So what you need to do is something like this:
...
var t = closure.DefineGenericParameters("A")[0];
var iFunctionType = typeof(Function<,>).MakeGenericType(t, t);
closure.AddInterfaceImplementation(iFunctionType);
...
You've still got some other problems (e.g. your IL for the apply method isn't valid), but this should at least unblock you enough to use PEVerify.

How to use Mono.Cecil to parse IL Instructions from byte array

I am dynamically compiling source code using CodeDOM,
now i want to work with the generated IL code of a particular method using Cecil, CodeDOM provides me with the IL code of the method as a byte array, is there any way to create a MethodBody, (or just an array of Mono.Cecil.Cil.Instruction) from that bytecode without saving the assembly and going from there?
There is functionality in Cecil that parses binary IL. It's in the class CodeReader in the Mono.Cecil.Cil namespace.
The method ReadCode does more or less what you want. But the class is set up in a way that you can't just pass in a byte[]. In general, you need to resolve metadata tokens, e.g. for method calls. CodeReader requires a MetadataReader via constructor to do this and MetadataReader in turn requires a ModuleDefinition.
There is an alternative if you don't use Cecil. Use SDILReader:
// get the method that you want to extract the IL from
MethodInfo methodInfo = typeof(Foo).GetMethod("Bar", BindingFlags.Static | BindingFlags.NonPublic);
Globals.LoadOpCodes();
// doesn't work on DynamicMethod
MethodBodyReader reader = new MethodBodyReader(methodInfo);
List<ILInstruction> instructions = reader.instructions;
string code = reader.GetBodyCode();
Another alternative is ILReader from ILVisualizer 2010 Solution.
DynamicMethod dynamicMethod = new DynamicMethod("HelloWorld", typeof(void), new Type[] { }, typeof(Program), false);
ILGenerator ilGenerator = dynamicMethod.GetILGenerator();
ilGenerator.Emit(OpCodes.Ldstr, "hello, world");
ilGenerator.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
ilGenerator.Emit(OpCodes.Ret);
MethodBodyInfo methodBodyInfo = MethodBodyInfo.Create(dynamicMethod);
string ilCode = string.Join(Environment.NewLine, methodBodyInfo.Instructions);
// get the method that you want to extract the IL from
MethodInfo methodInfo = typeof(Foo).GetMethod("Bar", BindingFlags.Static | BindingFlags.NonPublic);
MethodBodyInfo methodBodyInfo2 = MethodBodyInfo.Create(methodInfo);
string ilCode2 = string.Join(Environment.NewLine, methodBodyInfo2.Instructions);

Create a class type in code in .net c#

When I was looking to the System.Linq.Expression capabilities (creating expression trees in code, compiling them, executing them) I was asking myself if this is possible for class creation as well - specifically generic classes.
I would expect something like Expression.Class() or Expression.GenericClass(). Looking at the methods I did not see any of those. It would be very practical, since I could build business objects dynamically - on the fly. Actually that is what I need. If there is another approach to that in .net c# that is also of interest to me.
There is an example of how to do this in All-In-One Framework codeplex project
http://1code.codeplex.com/
// Define the assembly and the module.
AppDomain appDomain = AppDomain.CurrentDomain;
AssemblyName assemblyName = new AssemblyName("EmittedAssembly");
AssemblyBuilder assembly = appDomain.DefineDynamicAssembly(
assemblyName, AssemblyBuilderAccess.RunAndSave);
// An assembly is made up of executable modules. For a single-module
// assembly, the module name and file name are the same as the
// assembly name.
ModuleBuilder module = assembly.DefineDynamicModule(
assemblyName.Name, assemblyName.Name + ".dll");
/////////////////////////////////////////////////////////////////////
// Declare the types (classes).
//
// Declare the class "ClassA"
TypeBuilder classA = module.DefineType("ClassA", TypeAttributes.Public);
// Declare the class "ClassB"
TypeBuilder classB = module.DefineType("ClassB", TypeAttributes.Public);
// Define the fields stringField, classBField
FieldBuilder stringField = classA.DefineField("stringField",
typeof(string), FieldAttributes.Private);
FieldBuilder classBField = classA.DefineField("classBField",
classB, FieldAttributes.Public);
/////////////////////////////////////////////////////////////////////
// Define the property ClassBProperty
PropertyBuilder classBProperty = classA.DefineProperty(
"ClassBProperty", PropertyAttributes.None, classB, null);
// The special set of attributes for the property set&get methods
MethodAttributes getSetAttr = MethodAttributes.Public |
MethodAttributes.SpecialName | MethodAttributes.HideBySig;
// Define the "get" accessor method for ClassBProperty
MethodBuilder classBGetProp = classA.DefineMethod(
"get_ClassBProperty", getSetAttr, classB, Type.EmptyTypes);
ILGenerator classBGetIL = classBGetProp.GetILGenerator();
classBGetIL.Emit(OpCodes.Ldarg_0);
classBGetIL.Emit(OpCodes.Ldfld, classBField);
classBGetIL.Emit(OpCodes.Ret);
// Define the "set" accessor method for ClassBProperty
MethodBuilder classBSetProp = classA.DefineMethod(
"set_ClassBProperty", getSetAttr, null, new Type[] { classB });
ILGenerator sampleSetIL = classBSetProp.GetILGenerator();
sampleSetIL.Emit(OpCodes.Ldarg_0);
sampleSetIL.Emit(OpCodes.Ldarg_1);
sampleSetIL.Emit(OpCodes.Stfld, classBField);
sampleSetIL.Emit(OpCodes.Ret);
// Map the get&set methods to PropertyBuilder
classBProperty.SetGetMethod(classBGetProp);
classBProperty.SetSetMethod(classBSetProp);
/////////////////////////////////////////////////////////////////////
// Define a method that uses the classBField
MethodBuilder classAMethod = classA.DefineMethod("ClassAMethod",
MethodAttributes.Public);
// Define the list generics and ienumerable generic
Type listOf = typeof(List<>);
Type enumOf = typeof(IEnumerable<>);
Type listOfClassA = listOf.MakeGenericType(classA);
Type enumOfClassA = enumOf.MakeGenericType(classA);
// Define the method, ClassBMethod, for ClassB
MethodBuilder classBMethod = classB.DefineMethod("ClassBMethod",
MethodAttributes.Public, typeof(void), new Type[] { listOfClassA });
classBMethod.DefineParameter(1, ParameterAttributes.None, "list");
// Write the body of ClassAMethod that calls ClassBMethod
ILGenerator ilgenA = classAMethod.GetILGenerator();
ilgenA.Emit(OpCodes.Nop);
ilgenA.Emit(OpCodes.Ldarg_0);
ilgenA.Emit(OpCodes.Ldfld, classBField);
ilgenA.Emit(OpCodes.Ldnull);
ilgenA.Emit(OpCodes.Callvirt, classBMethod);
ilgenA.Emit(OpCodes.Ret);
/////////////////////////////////////////////////////////////////////
// Create the types.
//
classA.CreateType();
classB.CreateType();
/////////////////////////////////////////////////////////////////////
// Save the assembly.
//
assembly.Save(assemblyName.Name + ".dll");
Sorry this is a bit long.. :-P
You should look into the CSharpCodeProvider or you can look into the dynamic feature of .Net4. Both will allow you to create new object types in code which can be instantiated.

Categories

Resources