Tutorial :Is there a way to build a new type during Runtime?



Question:

I am going to ask a question that might sound weird.

Is there a way to build a new class during Runtime? Or at least, add a new property to an existing class.

I mean creating a class that doesn't exist and not an instance of an existing class. I could later on use reflections to load and use this class.


Solution:1

Adding a property to an existing type is not possible, but you can create a new type at runtime using Reflection.Emit. It's pretty complicated stuff, and it goes something like this:

AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(        assemblyName , AssemblyBuilderAccess.Run, assemblyAttributes);  ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("ModuleName");  TypeBuilder typeBuilder = moduleBuilder.DefineType(        "MyNamespace.TypeName" , TypeAttributes.Public);    typeBuilder.DefineDefaultConstructor(MethodAttributes.Public);    // Add a method  newMethod = typeBuilder.DefineMethod("MethodName" , MethodAttributes.Public);    ILGenerator ilGen = newMethod.GetILGenerator();    // Create IL code for the method  ilGen.Emit(...);    // ...    // Create the type itself  Type newType = typeBuilder.CreateType();  

This code is just a sample. It could contain errors.

You can also generate classes by compiling C# source code at runtime using System.CodeDom, but I don't know a lot about that.


Solution:2

This is not a weird question - in some cases it might be very useful. For instance I use this technique for performance tests sometimes:

public static Type[] DynamicTypes;    public void CreateObjects()  {    var codeNamespace = new CodeNamespace( "DynamicClasses" );    codeNamespace.Imports.Add( new CodeNamespaceImport( "System" ) );    codeNamespace.Imports.Add( new CodeNamespaceImport( "System.ComponentModel" ) );      for( var i = 0; i < 2000; i++ )    {      var classToCreate = new CodeTypeDeclaration( "DynamicClass_" + i )      {        TypeAttributes = TypeAttributes.Public      };      var codeConstructor1 = new CodeConstructor      {        Attributes = MemberAttributes.Public      };      classToCreate.Members.Add( codeConstructor1 );        codeNamespace.Types.Add( classToCreate );    }      var codeCompileUnit = new CodeCompileUnit();    codeCompileUnit.Namespaces.Add( codeNamespace );      var compilerParameters = new CompilerParameters    {      GenerateInMemory = true,      IncludeDebugInformation = true,      TreatWarningsAsErrors = true,      WarningLevel = 4    };    compilerParameters.ReferencedAssemblies.Add( "System.dll" );      var compilerResults = new CSharpCodeProvider().CompileAssemblyFromDom( compilerParameters, codeCompileUnit );      if( compilerResults == null )    {      throw new InvalidOperationException( "ClassCompiler did not return results." );    }    if( compilerResults.Errors.HasErrors )    {      var errors = string.Empty;      foreach( CompilerError compilerError in compilerResults.Errors )      {        errors += compilerError.ErrorText + "\n";      }      Debug.Fail( errors );      throw new InvalidOperationException( "Errors while compiling the dynamic classes:\n" + errors );    }      var dynamicAssembly = compilerResults.CompiledAssembly;    DynamicTypes = dynamicAssembly.GetExportedTypes();  }  


Solution:3

Take a look at the System.Reflection.Emit namespace. I've never used it myself but the classes in this namespace can be used to generate IL (intermediate language).


Solution:4

You might take a look at the System.CodeDom namespace. According to one of the pages linked from there:

The .NET Framework includes a mechanism called the Code Document Object Model (CodeDOM) that enables developers of programs that emit source code to generate source code in multiple programming languages at run time, based on a single model that represents the code to render.

I'm not at all an expert in this, I just remembered seeing it on my .NET Framework poster on my wall. :)

Edit: Since writing this answer, I have played with System.CodeDom a bit. I've written a blog post that uses some basic CodeDom that may help those wanting to get started with it.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »