Dynamically Create a Class at Runtime

Introduction
 
Normally we are create a class at design time using the class keyword in applications. Have you ever created a class at run time? This illustration describes how to create a class at run time. For creating a class dynamically at run time, this illustration uses the following classes that satisfies the majority of the requirements.
  • AssemblyName
  • AssemblyBuilder 
  • ModuleBuilder 
  • TypeBuilder
  • FieldBuilder
  • PropertyBuilder
Let's discuss the preceding classes a little. 
 
AssemblyName
 
The Assembly Name class in the System.Reflection namespace initializes a new instance of the System.Reflection.AssemblyName class with the specified display name. For more details Visit the link
 
Example:
  1. AssemblyName asemblyName;  
  2. this.asemblyName = new AssemblyName(ClassName);   
In the preceding code ClassName is a variable, that contains the class name to be created. 
 
AssemblyBuilder
 
This class helps to create a dynamic assembly at run time. This is a sealed class and has no constructor. The object of this class is created using the DefineDynamicAssembly method of the AppDomain class. To learn more.
 
Example:
  1. AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(this.asemblyName, AssemblyBuilderAccess.Run);
ModuleBuilder
 
This class dynamically creates a module in the project. It inherits from the Module class in System.Reflection.Emit and impliments a _ModuleBuilder interface. This class also has no constructor, hence an object of the class can be created using the DefineDynamicModule function of the assembly builder class. To learn more.
  1. ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");  
Note: MainModule is the name of the module to be created at run time. 
 
TypeBuilder
 
TypeBuilder creates a new instance of the class specified by the name and inherits from System.Reflection.TypeInfo. This is also a sealed class and cannot be directly created by an object of this class. It comes from the System.Reflection.Emit namespace, the function DefineType of the ModuleBuilder class creates an object of this class.
 
Example: 
  1. TypeBuilder typeBuilder = moduleBuilder.DefineType(this.asemblyName.FullName  
  2.                               , TypeAttributes.Public |  
  3.                               TypeAttributes.Class |  
  4.                               TypeAttributes.AutoClass |  
  5.                               TypeAttributes.AnsiClass |  
  6.                               TypeAttributes.BeforeFieldInit |  
  7.                               TypeAttributes.AutoLayout  
  8.                               , null);  
FieldBuilder
 
This class cannot be inherited and used to create a field or variable of a class. It inherits from the System.Reflection.FieldInfo class. The DefineField function of the typebilder class creates an object of this class.
 
Example:  
  1. FieldBuilder fieldBuilder = typeBuilder.DefineField("_" + propertyName, propertyType, FieldAttributes.Private);  
Note: The DefineField function takes the three parameter names of property, datatype and access specifier.
 
PropertyBuilder 
 
This class defines or creates a property of a class at runtime, it is in the System.Reflection.Emit namespace and cannot be inherited. This class inherites from the System.Reflection.PropertyInfo class. The DefineProperty function of the typebuilder class creates an object of the PropertyBuilder class.
 
Example:
  1. PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null);  
Getting Started
 
Here in this article I have dynamically created a class using a console application and their three properties. Then displayed the information of the class in the screen.
 
Use the following procedure to create a class:
  • Create assembly
  • Create Module
  • Create Instance
  • Create constructor 
  • Create properties
Create assembly 
 
Before creating an instance of the class you need to create or define the assembly of class as in the following:
  1. AssemblyName asemblyName;  
  2. this.asemblyName = new AssemblyName(ClassName);  
  3. AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(this.asemblyName, AssemblyBuilderAccess.Run);  
In the preceding  code .02 defines assembly name of class using AssemblyName class and 03 creates assembly dynamically by assemblybuilder class.
 
Create Module
 
Using the module builder class create the module of the class, as mentioned above the DefineDynamicModule function creates an object of the class. This function takes a string as module name.
  1. ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");  
Create Instance
 
As I mentioned above, the TypeBuilder class creates an instance of a class and creates an object of a TypeBuilder class using the module's DefineType function as in the following code:
  1. TypeBuilder typeBuilder = moduleBuilder.DefineType(this.asemblyName.FullName  
  2.                               , TypeAttributes.Public |  
  3.                               TypeAttributes.Class |  
  4.                               TypeAttributes.AutoClass |  
  5.                               TypeAttributes.AnsiClass |  
  6.                               TypeAttributes.BeforeFieldInit |  
  7.                               TypeAttributes.AutoLayout  
  8.                               , null);  
The preceding code creates an instance of the class and defines their character. Here the class is a public type and defines an assembly of the class and module.
 
Create constructor
 
After creating the class, create their constructor using the DefineDefaultConstructor function typebuilder class.
  1. typeBuilder.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);  
The preceding code creates the constructor of the class with their character like access specifier. Here the constructor's access specifier is public.
 
Create properties
 
Creating a property is a little bit of a long process. To create a property of a class, we need to define the field of that property and the get and set methods, the following code creates a class's property with their get and set method.
  1. FieldBuilder fieldBuilder = typeBuilder.DefineField("_" + propertyName, propertyType, FieldAttributes.Private);  
  2.   
  3.           PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null);  
  4.           MethodBuilder getPropMthdBldr = typeBuilder.DefineMethod("get_" + propertyName, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, propertyType, Type.EmptyTypes);  
  5.           ILGenerator getIl = getPropMthdBldr.GetILGenerator();  
  6.   
  7.           getIl.Emit(OpCodes.Ldarg_0);  
  8.           getIl.Emit(OpCodes.Ldfld, fieldBuilder);  
  9.           getIl.Emit(OpCodes.Ret);  
  10.   
  11.           MethodBuilder setPropMthdBldr =typeBuilder.DefineMethod("set_" + propertyName,  
  12.                 MethodAttributes.Public |  
  13.                 MethodAttributes.SpecialName |  
  14.                 MethodAttributes.HideBySig,  
  15.                 nullnew[] { propertyType });  
  16.   
  17.           ILGenerator setIl = setPropMthdBldr.GetILGenerator();  
  18.           Label modifyProperty = setIl.DefineLabel();  
  19.           Label exitSet = setIl.DefineLabel();  
  20.   
  21.           setIl.MarkLabel(modifyProperty);  
  22.           setIl.Emit(OpCodes.Ldarg_0);  
  23.           setIl.Emit(OpCodes.Ldarg_1);  
  24.           setIl.Emit(OpCodes.Stfld, fieldBuilder);  
  25.   
  26.           setIl.Emit(OpCodes.Nop);  
  27.           setIl.MarkLabel(exitSet);  
  28.           setIl.Emit(OpCodes.Ret);  
  29.   
  30.           propertyBuilder.SetGetMethod(getPropMthdBldr);  
  31.           propertyBuilder.SetSetMethod(setPropMthdBldr);  
The following class is the full code for creating a class dynamically at runtime. See the full code.
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Reflection;  
  5. using System.Reflection.Emit;  
  6. using System.Text;  
  7. using System.Threading.Tasks;  
  8.   
  9. namespace PropertyBuilderExample  
  10. {  
  11.    public class MyClassBuilder  
  12.     {  
  13.        AssemblyName asemblyName;  
  14.        public MyClassBuilder(string ClassName)  
  15.        {  
  16.            this.asemblyName = new AssemblyName(ClassName);  
  17.        }  
  18.        public object CreateObject(string[] PropertyNames,Type[]Types)  
  19.        {  
  20.            if(PropertyNames.Length!=Types.Length)  
  21.            {  
  22.               Console.WriteLine("The number of property names should match their corresopnding types number");  
  23.            }  
  24.   
  25.              TypeBuilder DynamicClass = this.CreateClass();  
  26.              this.CreateConstructor(DynamicClass);  
  27.             for(int ind=0;ind<PropertyNames.Count();ind++)  
  28.                CreateProperty(DynamicClass, PropertyNames[ind],Types[ind]);  
  29.             Type type = DynamicClass.CreateType();  
  30.   
  31.            return Activator.CreateInstance(type);  
  32.        }  
  33.        private TypeBuilder CreateClass()  
  34.        {  
  35.            AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(this.asemblyName, AssemblyBuilderAccess.Run);  
  36.            ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");  
  37.            TypeBuilder typeBuilder = moduleBuilder.DefineType(this.asemblyName.FullName  
  38.                                , TypeAttributes.Public |  
  39.                                TypeAttributes.Class |  
  40.                                TypeAttributes.AutoClass |  
  41.                                TypeAttributes.AnsiClass |  
  42.                                TypeAttributes.BeforeFieldInit |  
  43.                                TypeAttributes.AutoLayout  
  44.                                , null);  
  45.            return typeBuilder;  
  46.        }  
  47.        private void CreateConstructor(TypeBuilder typeBuilder)  
  48.        {  
  49.            typeBuilder.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);  
  50.        }  
  51.        private void CreateProperty(TypeBuilder typeBuilder, string propertyName, Type propertyType)  
  52.        {  
  53.            FieldBuilder fieldBuilder = typeBuilder.DefineField("_" + propertyName, propertyType, FieldAttributes.Private);  
  54.   
  55.            PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null);  
  56.            MethodBuilder getPropMthdBldr = typeBuilder.DefineMethod("get_" + propertyName, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, propertyType, Type.EmptyTypes);  
  57.            ILGenerator getIl = getPropMthdBldr.GetILGenerator();  
  58.   
  59.            getIl.Emit(OpCodes.Ldarg_0);  
  60.            getIl.Emit(OpCodes.Ldfld, fieldBuilder);  
  61.            getIl.Emit(OpCodes.Ret);  
  62.   
  63.            MethodBuilder setPropMthdBldr =typeBuilder.DefineMethod("set_" + propertyName,  
  64.                  MethodAttributes.Public |  
  65.                  MethodAttributes.SpecialName |  
  66.                  MethodAttributes.HideBySig,  
  67.                  nullnew[] { propertyType });  
  68.   
  69.            ILGenerator setIl = setPropMthdBldr.GetILGenerator();  
  70.            Label modifyProperty = setIl.DefineLabel();  
  71.            Label exitSet = setIl.DefineLabel();  
  72.   
  73.            setIl.MarkLabel(modifyProperty);  
  74.            setIl.Emit(OpCodes.Ldarg_0);  
  75.            setIl.Emit(OpCodes.Ldarg_1);  
  76.            setIl.Emit(OpCodes.Stfld, fieldBuilder);  
  77.   
  78.            setIl.Emit(OpCodes.Nop);  
  79.            setIl.MarkLabel(exitSet);  
  80.            setIl.Emit(OpCodes.Ret);  
  81.   
  82.            propertyBuilder.SetGetMethod(getPropMthdBldr);  
  83.            propertyBuilder.SetSetMethod(setPropMthdBldr);  
  84.        }  
  85.     }  
  86. }  
The following is the code for displaying the class details that were created at run time.
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Reflection;  
  5. using System.Reflection.Emit;  
  6. using System.Text;  
  7. using System.Threading.Tasks;  
  8. using PropertyBuilderExample;  
  9.   
  10. namespace PropertyBuilderExample  
  11. {  
  12.     class Program  
  13.     {  
  14.         static void Main(string[] args)  
  15.         {  
  16.             MyClassBuilder MCB=new MyClassBuilder("Student");  
  17.             var myclass = MCB.CreateObject(new string[3] { "ID""Name""Address" }, new Type[3] { typeof(int), typeof(string), typeof(string) });  
  18.            Type TP = myclass.GetType();  
  19.               
  20.             foreach (PropertyInfo PI in TP.GetProperties())  
  21.             {  
  22.                 Console.WriteLine(PI.Name);  
  23.             }  
  24.             Console.ReadLine();  
  25.         }  
  26.     }  
  27. }   
Summery
 
I hope you have learned how to create a class dynamically at run time.


Similar Articles