Create anonymous types at runtime in C#

I am working on a project where I need to generate anonymous types at run-time based on some user input.

In order to do it, you will first need a pseudo-assembly where all the dynamic types will be stored:

AssemblyBuilder dynamicAssembly =
        AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("MyDynamicAssembly"),
            AssemblyBuilderAccess.Run);

Then you need a module. You might be wondering what a module is. Every assembly has at least one module. In theory an assembly can contain multiple modules. And types belong to a module. So to summarize:

Assemblies contain modules and modules contain types

As Visual Studio doesn’t seem to support the creation of multi-module assemblies, you actually almost never need to care about modules. But you do need one to add types to an assembly. So let’s add a module to our assembly:

ModuleBuilder dynamicModule = dynamicAssembly.DefineDynamicModule("MyDynamicAssemblyModule");

Then we’ll create our dynamic type builder:

TypeBuilder dynamicType = dynamicModule.DefineType("MyDynamicType", TypeAttributes.Public);

Now that you have the type builder, you can create the type. But first I needed to add some properties backed by fields. This is a little bit trickier. At first I thought it’s enough to do something like this:

PropertyBuilder property = dynamicType.DefineProperty(propertyName, PropertyAttributes.None, propertyType, new[] {propertyType});

Unfortunately it just seems to create a property with no getter or setter, which is not very useful. Since I couldn’t find anyway to tell the DefineProperty method I needed more than an empty property, I decided to check the intermediate language code for some properties of a class and see what happened there.

In order to see the intermediate language code for a class, you have a few possibilities:

  • Use Sil. It is free and provides both a Visual Studio Addin and a standalone application.
  • ILSpy which is a free standalone application.
  • .Net Reflector which is a commercial standalone application as well as Visual Studio Addin.
  • other tools (there are plenty of tools out there but I’ve only ever used the three above.

So I created a simple auto-property called MyProperty and looked at the code generated by the C# compiler.

First the property definition itself:

  .property instance object MyProperty()
  {
    .get instance object MyNamespace.MyTestClass::get_MyProperty()
    .set instance void MyNamespace.MyTestClass::set_MyProperty(object)
  } // end of property MyTestClass::MyProperty

So no surprise here. It just links to getter and setter of the property to the get_MyProperty and set_MyProperty methods. Here the generated intermediate language code for these two methods:

  .method public hidebysig specialname instance object 
          get_MyProperty() cil managed
  {
    .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
    // Code size       11 (0xb)
    .maxstack  1
    .locals init (object V_0)
    IL_0000:  ldarg.0
    IL_0001:  ldfld      object MyNamespace.MyTestClass::'<MyProperty>k__BackingField'
    IL_0006:  stloc.0
    IL_0007:  br.s       IL_0009

    IL_0009:  ldloc.0
    IL_000a:  ret
  } // end of method MyTestClass::get_MyProperty

  .method public hidebysig specialname instance void 
          set_MyProperty(object 'value') cil managed
  {
    .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
    // Code size       8 (0x8)
    .maxstack  8
    IL_0000:  ldarg.0
    IL_0001:  ldarg.1
    IL_0002:  stfld      object MyNamespace.MyTestClass::'<MyProperty>k__BackingField'
    IL_0007:  ret
  } // end of method MyTestClass::set_MyProperty

The code for set_MyProperty is pretty straightforward:

  1. Load the object on the evaluation stack
  2. Load the value on the evaluation stack
  3. Replace the value of the backing field of the object with the value on the stack

But the get_MyProperty code seemed to complex. It’s basically doing the following:

  1. Load the object on the evaluation stack
  2. Get the value of the backing field of this object on the stack
  3. Store the value from the stack in the local variable list
  4. Jump to the next instruction
  5. Load the value from the local variable list to the stack

Basically the last 3 steps are not required. So you can optimize it to just loading the object and fetching the value of the backing field to the stack.

OK, now we know what we need to do:

  1. Define a backing field
  2. Define a property
  3. Define a get method
  4. Execute the IL code above
  5. Define a set method
  6. Execute the IL code above

That sounds very complex just to define a property dynamically but I haven’t found any easier way. The code then looks like this:

public static void AddProperty(TypeBuilder typeBuilder, string propertyName, Type propertyType)
{
    const MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.HideBySig;

    FieldBuilder field = typeBuilder.DefineField("_" + propertyName, typeof (string), FieldAttributes.Private);
    PropertyBuilder property = typeBuilder.DefineProperty(propertyName, PropertyAttributes.None, propertyType,
        new[] {propertyType});

    MethodBuilder getMethodBuilder = typeBuilder.DefineMethod("get_value", getSetAttr, propertyType,
        Type.EmptyTypes);
    ILGenerator getIl = getMethodBuilder.GetILGenerator();
    getIl.Emit(OpCodes.Ldarg_0);
    getIl.Emit(OpCodes.Ldfld, field);
    getIl.Emit(OpCodes.Ret);

    MethodBuilder setMethodBuilder = typeBuilder.DefineMethod("set_value", getSetAttr, null,
        new[] {propertyType});
    ILGenerator setIl = setMethodBuilder.GetILGenerator();
    setIl.Emit(OpCodes.Ldarg_0);
    setIl.Emit(OpCodes.Ldarg_1);
    setIl.Emit(OpCodes.Stfld, field);
    setIl.Emit(OpCodes.Ret);

    property.SetGetMethod(getMethodBuilder);
    property.SetSetMethod(setMethodBuilder);
}

Once you’ve called this method to add the property (or multiple properties), all you have to do is call the CreateType method on the TypeBuilder to get an actual dynamic type:

Type myType = dynamicType.CreateType();

That’s it ! It took me forever to figure out but I learned a lot along the way !

5 thoughts on “Create anonymous types at runtime in C#

  1. Great article, but I have a problem that I found when one of the properties is DateTime and trying to set the value of the property it is not set…

  2. icant run the code

    private void Form1_Load(object sender, EventArgs e)
    {
    AssemblyBuilder dynamicAssembly =
    AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName(“MyDynamicAssembly”),
    AssemblyBuilderAccess.Run);

    string propertyName = “prp_1”;
    Type propertyType = new Type();

    ModuleBuilder dynamicModule = dynamicAssembly.DefineDynamicModule(“MyDynamicAssemblyModule”);
    TypeBuilder dynamicType = dynamicModule.DefineType(“MyDynamicType”, TypeAttributes.Public);
    PropertyBuilder property = dynamicType.DefineProperty(propertyName, System.Reflection.PropertyAttributes.None,
    propertyType, new[] { propertyType });

    //call this first
    AddProperty(dynamicType, propertyName, propertyType );

    //then we ‘ ll dynamic type
    Type myType = dynamicType.CreateType();

    }

    public static void AddProperty(TypeBuilder typeBuilder, string propertyName, Type propertyType)
    {
    const MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.HideBySig;

    FieldBuilder field = typeBuilder.DefineField(“_” + propertyName, typeof(string), FieldAttributes.Private);
    PropertyBuilder property = typeBuilder.DefineProperty(propertyName, System.Reflection.PropertyAttributes.None, propertyType,
    new[] { propertyType });

    MethodBuilder getMethodBuilder = typeBuilder.DefineMethod(“get_value”, getSetAttr, propertyType,
    Type.EmptyTypes);
    ILGenerator getIl = getMethodBuilder.GetILGenerator();
    getIl.Emit(OpCodes.Ldarg_0);
    getIl.Emit(OpCodes.Ldfld, field);
    getIl.Emit(OpCodes.Ret);

    MethodBuilder setMethodBuilder = typeBuilder.DefineMethod(“set_value”, getSetAttr, null,
    new[] { propertyType });
    ILGenerator setIl = setMethodBuilder.GetILGenerator();
    setIl.Emit(OpCodes.Ldarg_0);
    setIl.Emit(OpCodes.Ldarg_1);
    setIl.Emit(OpCodes.Stfld, field);
    setIl.Emit(OpCodes.Ret);

    property.SetGetMethod(getMethodBuilder);
    property.SetSetMethod(setMethodBuilder);
    }

  3. Good article and code. However, I just found a bug in it. The static AddProperty method is defining all backing fields as strings instead of using the same base type as the property.

    Besically just replace this:
    FieldBuilder field = typeBuilder.DefineField(“_” + propertyName, typeof (string), FieldAttributes.Private);

    By this:
    FieldBuilder field = typeBuilder.DefineField(“_” + propertyName, propertyType, FieldAttributes.Private);

Leave a Reply

Your email address will not be published.