Search code examples
c#system.reflectionreflection.emitcodedomintermediate-language

How can I create a class at runtime in c#? I want the class to be created physically in my file system


I am developing an extension that must create classes with just the user giving class name and property info and some more which i will be extending later.

I also want to add necessary namespaces.

I have seen many questions addressing this. I tried solutions that use reflection.emit , CodeDom but none seems to create classes physically in my file system. Is there anywhere to look at or start with?

By physical class I meant to say , the cs files should show up in my file system.I am talking about a generic class having constructor and some properties, functions.


Solution

  • You can use the Microsoft CodeDom to do this. Some sample code is below.

    The easiest way to use this code is to create a new 'Console App (.NET Core)' in Visual Studio, and just overwrite the contents of the Program class (overwrite the Main method). Then hover over the squigglies and Visual Studio lightbulb will suggest 'Install package System.CodeDom'. Do this for the latest version, and add a 'using System.CodeDom.Compiler' and it should compile.

    If you run it it generates a file called MyClass.cs in the bin/Debug/netcoreapp3.1 folder which has C# code for a class with a property and a method. The names and types are set in the code below as you can see.

    Microsoft has good documentation for this stuff: there's a page that also shows how to compile and run code generated in this way.

    using System;
    using System.CodeDom;
    using System.CodeDom.Compiler;
    
    namespace ConsoleApp1
    {
        class Program
        {
            static void Main()
            {
                string codeFileName = "MyClass.cs";
                CodeCompileUnit codeCompileUnit = CreateClass();
                CodeDomProvider codeDomProvider = CodeDomProvider.CreateProvider("CSharp");
                IndentedTextWriter tw = new IndentedTextWriter(new System.IO.StreamWriter(codeFileName, false), "    ");
                codeDomProvider.GenerateCodeFromCompileUnit(codeCompileUnit, tw, new CodeGeneratorOptions());
                tw.Close();
            }
    
            public static CodeCompileUnit CreateClass()
            {
                CodeCompileUnit compileUnit = new CodeCompileUnit();
    
                CodeNamespace samples = new CodeNamespace("MyNamespace");
                compileUnit.Namespaces.Add(samples);
    
                CodeTypeDeclaration class1 = new CodeTypeDeclaration("MyClass");
                samples.Types.Add(class1);
    
                CodeMemberField field1 = new CodeMemberField("System.String", "myField");
                class1.Members.Add(field1);
    
                CodeMemberProperty property1 = new CodeMemberProperty();
                property1.Name = "MyProperty";
                property1.Type = new CodeTypeReference("System.String");
                property1.Attributes = MemberAttributes.Public;
                property1.GetStatements.Add(new CodeMethodReturnStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "myField")));
                property1.SetStatements.Add(new CodeAssignStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "myField"), new CodePropertySetValueReferenceExpression()));
                class1.Members.Add(property1);
    
                CodeMemberMethod method1 = new CodeMemberMethod();
                method1.Name = "MyMethod";
                method1.ReturnType = new CodeTypeReference("System.String");
                method1.Parameters.Add(new CodeParameterDeclarationExpression("System.String", "myParameter"));
                method1.Statements.Add(new CodeMethodReturnStatement(new CodeArgumentReferenceExpression("myParameter")));
                class1.Members.Add(method1);
    
                return compileUnit;
            }
        }
    }