0

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.

Louis Go
  • 2,213
  • 2
  • 16
  • 29

1 Answers1

0

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;
        }
    }
}
Rich N
  • 8,939
  • 3
  • 26
  • 33
  • Thanks, it did create class when i run it as a console project. Is it possible to change the location in which the class will be created – Naresh_drake Mar 03 '20 at 10:50
  • Sure: just change the codeFileName to include a path. It can be a relative path. 'string codeFileName = @"c:/DotNet/MyClass.cs";' will put the file in c:/DotNet. 'string codeFileName = @"../../../MyClass.cs";' will put the file in the same folder as the csproj, three levels up from original folder. – Rich N Mar 03 '20 at 11:04
  • Yes thanks that too worked. Can CodeDom be used to add properties to a existing class? or add properties to a class which was created by codedom. – Naresh_drake Mar 04 '20 at 10:44
  • I'm not sure what you mean. If you want to read the code file we just created back in, parse it, and modify it using the CodeDom, then I don't think you can easily do that: you need a parser. If you mean can you change classes dynamically in memory then the dynamic keyword lets you do that. In any case I think this is a new question, not a comment! – Rich N Mar 06 '20 at 21:30