Generate code for generic nested class with Reflection.Emit - c#

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.

Related

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.

How to make .NET reflection to work with dynamically generated objects? [duplicate]

This question already has answers here:
How do I reflect over the members of dynamic object?
(5 answers)
Closed 8 years ago.
Look at the following example:
void Main()
{
// APPROACH 1: With an anonymous type
var myObject = new {
Property1 = "PropertyValue1"
};
// WORKS: Properties contains "Property1"
var properties = myObject.GetType().GetProperties();
// APPROACH 2: With an expando object
dynamic myObject2 = new ExpandoObject();
myObject2.Property1 = "PropertyValue1";
// DOES NOT WORK: Properties2 is null or empty
var properties2 = myObject2.GetType().GetProperties();
}
What I want is to make Type.GetProperties() to work on a dynamically generated type. I really understand why it works in the approach 1 and not 2. Actually, in the approach 1, the compiler has the oportunity to generate an anonymous type that looks exactly like a named type. In the approach 2, however, the compile time type is actually an ExpandoObject, so reflection doesn't work properly.
How do I create a runtime object, that is dynamic and will also work normally with reflection, like the GetProperties method?
EDIT
Thanks for all answers, but I really understand and I know how to get the keys and values from the ExpandoObject.. The problem is that I need to pass a dynamically created instance to a method, outside my control that will, in turn, call GetProperties() on the instance.
You don't need reflection with ExpandoObject. It's really just a fancy implementation of IDictionary<string, object>. You can cast it as such, and then you will have a dictionary where the keys are the property names and the values are the property values:
// Create your object
dynamic myObject2 = new ExpandoObject();
// Cast to IDictionary<string, object>
var myObjectDictionary = (IDictionary<string, object>)myObject2;
// Get List<string> of properties
var propertyNames = myObjectDictionary.Keys.ToList();
Another option would be to use the features of an IDynamicMetaObjectProvider, which ExpandoObject also implements. Usage would look like:
var metaObjectProvider = (IDynamicMetaObjectProvider)myObject2;
var propertyNames = metaObjectProvider
.GetMetaObject(Expression.Constant(metaObjectProvider))
.GetDynamicMem‌​berNames();
In this case propertyNames would be an IEnumerable<string> with the dynamic member names.
In order to get the values via reflection for a dynamically-constructed type, you'll need to use Reflection.Emit. This is less than ideal as it requires you to properly emit MSIL. If your use case requires only simple property access, then it may be feasible, though ill-advised.
Here's a simple, lightly-tested, type builder that uses Reflection.Emit:
public static class TypeBuilderUtil {
public static Type BuildDynamicType() {
var typeBuilder = CreateTypeBuilder( "DynamicType" );
CreateProperty( typeBuilder, "Property1", typeof ( string ) );
var objectType = typeBuilder.CreateType();
return objectType;
}
private static TypeBuilder CreateTypeBuilder( string typeName ) {
var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly( new AssemblyName( "DynamicAssembly" ), AssemblyBuilderAccess.Run );
var moduleBuilder = assemblyBuilder.DefineDynamicModule( "DynamicModule" );
var typeBuilder = moduleBuilder.DefineType( typeName,
TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit | TypeAttributes.AutoLayout
, null );
return typeBuilder;
}
private static void CreateProperty( TypeBuilder typeBuilder, string propertyName, Type propertyType ) {
var backingFieldBuilder = typeBuilder.DefineField( "_" + propertyName, propertyType, FieldAttributes.Private );
var propertyBuilder = typeBuilder.DefineProperty( propertyName, PropertyAttributes.HasDefault, propertyType, null );
// Build setter
var getterMethodBuilder = typeBuilder.DefineMethod( "get_" + propertyName, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, propertyType, Type.EmptyTypes );
var getterIl = getterMethodBuilder.GetILGenerator();
getterIl.Emit( OpCodes.Ldarg_0 );
getterIl.Emit( OpCodes.Ldfld, backingFieldBuilder );
getterIl.Emit( OpCodes.Ret );
// Build setter
var setterMethodBuilder = typeBuilder.DefineMethod( "set_" + propertyName, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, null, new[] {propertyType} );
var setterIl = setterMethodBuilder.GetILGenerator();
setterIl.Emit( OpCodes.Ldarg_0 );
setterIl.Emit( OpCodes.Ldarg_1 );
setterIl.Emit( OpCodes.Stfld, backingFieldBuilder );
setterIl.Emit( OpCodes.Ret );
propertyBuilder.SetGetMethod( getterMethodBuilder );
propertyBuilder.SetSetMethod( setterMethodBuilder );
}
}
You would create the type, then populate it as such:
var myType = TypeBuilderUtil.BuildDynamicType();
var myObject = Activator.CreateInstance( myType );
// Set the value
var propertyInfo = myObject.GetType().GetProperty( "Property1", BindingFlags.Instance | BindingFlags.Public );
propertyInfo.SetValue( myObject, "PropertyValue", null );
Your first example is an anonymous object. The compiler actually generates a type behind the scenes that you can reflect on.
The second example uses an ExpandoObject to back your dynamic object. ExpandoObject has no properties of its own which is why your call returns what it does. ExpandoObject does explicitly implement IDictionary<string, object> that gives you access to the properties and their values. You can use it as follows:
var properties2 = (myObject2 as IDictionary<string, object>).Keys;
ExpandoObject is what is special here, nothing else. It's not actually mutating the definition of the type itself at runtime. What's actually going on here is that the apparent property accesses are actually mutating an IDictionary<string,object> that is held behind the scenes. To access the properties of an ExpandoObject (note this won't work for any other type) you can cast it to IDictionary<string,object>, which is the intended mechanism of getting that data from an ExpandoObject.

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

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).

If I build a type with a property using TypeBuilder do I need to use a propertyBuilder?

I want to use TypeBuilder to build a type that matches an interface. It's base type will be object, as I don't have any abstraction point.
The interface in question has a property like so::
public interface IFoo{
int Property{get;}
}
Do I need to actually create a PropertyBuilder? Or can I just get away with emitting a method for the int get_Property() method?
The CLI doesn't care about properties, as long as all the methods (which is all an interface really defines) have implementations:
var ab = AppDomain.CurrentDomain.DefineDynamicAssembly(
new AssemblyName("foo"), AssemblyBuilderAccess.RunAndSave);
var mb = ab.DefineDynamicModule("foo");
var tb = mb.DefineType("bar");
tb.AddInterfaceImplementation(typeof(IFoo));
var method = typeof(IFoo).GetProperty("Property").GetGetMethod();
var impl = tb.DefineMethod("impl",
MethodAttributes.Private | MethodAttributes.Virtual,
typeof(int), Type.EmptyTypes);
var il = impl.GetILGenerator();
il.Emit(OpCodes.Ldc_I4_7); // because it is lucky
il.Emit(OpCodes.Ret);
tb.DefineMethodOverride(impl, method);
var type = tb.CreateType();
IFoo foo = (IFoo)Activator.CreateInstance(type);
var val = foo.Property;
I would think you need to use a PropertyBuilder - a Property in .Net isn't as simple as having get_ and/or set_ methods - there's extra metadata needed.
I've never used TypeBuilder though, but I'd be pretty surprised if you could get away with just emitting a get_ method.

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