Sunday, July 31, 2016

Create dynamic class in C# using CodeDom

In C#, we can create classes at run-time and compile it to generate an assembly using System.CodeDom namespace in System.dll. For this, It provides different classes and functions to create the dynamic namespace add classes, methods and properties to it.
Let's start by adding a new Console application and add the namespace using System.CodeDom to it. We will create a namespace say 'sampleNamespace' by using the CodeNamespace class. So our code will look like the following:  
  1. CodeNamespace nameSpace = new CodeNamespace("sampleNameSpace");  
Next, we will add the using's to be used in the dynamic code. This is similar to adding the namespaces which we add normally in our applications as: using System or using System.Linq. To do this, we will use the Imports function in the CodeNamespace class. So our code will look like the following: 
  1. nameSpace.Imports.Add(new CodeNamespaceImport("System"));  
  2. nameSpace.Imports.Add(new CodeNamespaceImport("System.Linq"));  
  3. nameSpace.Imports.Add(new CodeNamespaceImport("System.Text"));  
Next we will add a class named SampleClass to our namespace sampleNamespace using the CodeTypeDeclaration class. It provides different properties like Name, IsClassAttributes etc. to create class definition and add this class to our namespace sampleNamespace. So the code will look like the following: 
  1. CodeTypeDeclaration cls = new CodeTypeDeclaration();  
  2. cls.Name = "SampleClass";  
  3. cls.IsClass = true;  
  4. cls.Attributes = MemberAttributes.Public;  
  5. nameSpace.Types.Add(cls);  
Next we will use the CodeCompileUnit class, which will acts as a container for the dynamic code that we are trying to generate. This container will be used to compile and generate an assembly of our code. Let's create a physical file on our system using the CodeCompileUnit class using the StreamWriiter class. So our code will change to the following:  
  1. CodeCompileUnit compileUnit = new CodeCompileUnit();  
  2. compileUnit.Namespaces.Add(nameSpace);  
  3. CSharpCodeProvider csharpcodeprovider = new CSharpCodeProvider();   
  4.   
  5. CSharpCodeProvider provider = new CSharpCodeProvider();  
  6.   
  7. using (StreamWriter sw = new StreamWriter(@"C:\SampleFile.cs"false))  
  8. {  
  9.     IndentedTextWriter tw = new IndentedTextWriter(sw, "    ");  
  10.     provider.GenerateCodeFromCompileUnit(compileUnit, tw, new CodeGeneratorOptions());  
  11.     tw.Close();  
  12. }  
So our complete code will look like below: 
  1.           CodeNamespace nameSpace = new CodeNamespace("sampleNameSpace");  
  2.   
  3.           nameSpace.Imports.Add(new CodeNamespaceImport("System"));  
  4.           nameSpace.Imports.Add(new CodeNamespaceImport("System.Linq"));  
  5.           nameSpace.Imports.Add(new CodeNamespaceImport("System.Text"));  
  6.   
  7.           CodeTypeDeclaration cls = new CodeTypeDeclaration();  
  8.           cls.Name = "SampleClass";  
  9.           cls.IsClass = true;  
  10.           cls.Attributes = MemberAttributes.Public;  
  11.           nameSpace.Types.Add(cls);  
  12.   
  13.           CodeCompileUnit compileUnit = new CodeCompileUnit();  
  14.           compileUnit.Namespaces.Add(nameSpace);  
  15.           CSharpCodeProvider csharpcodeprovider = new CSharpCodeProvider();   
  16.   
  17.           CSharpCodeProvider provider = new CSharpCodeProvider();  
  18.   
  19.           using (StreamWriter sw = new StreamWriter(@"D:\TestFile.cs"false))  
  20.           {  
  21.               IndentedTextWriter tw = new IndentedTextWriter(sw, "    ");  
  22.               provider.GenerateCodeFromCompileUnit(compileUnit, tw, new CodeGeneratorOptions());  
  23.               tw.Close();  
  24.           }  
Run the code and open the location to see the code file got generated with your code:
  1. //------------------------------------------------------------------------------  
  2. // <auto-generated>  
  3. //     This code was generated by a tool.  
  4. //     Runtime Version:4.0.30319.42000  
  5. //  
  6. //     Changes to this file may cause incorrect behavior and will be lost if  
  7. //     the code is regenerated.  
  8. // </auto-generated>  
  9. //------------------------------------------------------------------------------  
  10.   
  11. namespace sampleNameSpace {  
  12.     using System;  
  13.     using System.Linq;  
  14.     using System.Text;  
  15.       
  16.       
  17.     public class SampleClass {  
  18.     }  
  19. }  
So this was about how we can generate dynamic class with namespace using CodeDom classes. In next article we will see how we can add methods to these classes. Hope you enjoyed reading it. Happy coding...!!!