如何在运行时在 C# 中创建 class?我希望在我的文件系统中物理创建 class
How can I create a class at runtime in c#? I want the class to be created physically in my file system
我正在开发一个扩展程序,它必须创建 classes,只需用户提供 class 名称和 属性 信息以及我稍后将扩展的更多内容。
我还想添加必要的命名空间。
我看到很多关于这个的问题。我尝试了使用 reflection.emit 和 CodeDom 的解决方案,但 none 似乎在我的文件系统中物理地创建了 classes。有什么地方可以看或入手吗?
物理 class 我的意思是说,cs 文件应该出现在我的文件中 system.I 我在谈论一个通用的 class 具有构造函数和一些属性、函数。
您可以使用 Microsoft CodeDom 来执行此操作。下面是一些示例代码。
使用这段代码最简单的方法是在Visual Studio中新建一个'Console App (.NET Core)',并覆盖Program class的内容(覆盖Main方法)。然后将鼠标悬停在波浪形上,Visual Studio 灯泡会提示 'Install package System.CodeDom'。对最新版本执行此操作,并添加一个 'using System.CodeDom.Compiler' 它应该可以编译。
如果你 运行 它会在 bin/Debug/netcoreapp3.1 文件夹中生成一个名为 MyClass.cs 的文件,其中包含 class 和 属性 和一个方法。如您所见,名称和类型在下面的代码中设置。
Microsoft 对此有很好的文档:there's a page 还展示了如何编译和运行 以这种方式生成的代码。
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;
}
}
}
我正在开发一个扩展程序,它必须创建 classes,只需用户提供 class 名称和 属性 信息以及我稍后将扩展的更多内容。
我还想添加必要的命名空间。
我看到很多关于这个的问题。我尝试了使用 reflection.emit 和 CodeDom 的解决方案,但 none 似乎在我的文件系统中物理地创建了 classes。有什么地方可以看或入手吗?
物理 class 我的意思是说,cs 文件应该出现在我的文件中 system.I 我在谈论一个通用的 class 具有构造函数和一些属性、函数。
您可以使用 Microsoft CodeDom 来执行此操作。下面是一些示例代码。
使用这段代码最简单的方法是在Visual Studio中新建一个'Console App (.NET Core)',并覆盖Program class的内容(覆盖Main方法)。然后将鼠标悬停在波浪形上,Visual Studio 灯泡会提示 'Install package System.CodeDom'。对最新版本执行此操作,并添加一个 'using System.CodeDom.Compiler' 它应该可以编译。
如果你 运行 它会在 bin/Debug/netcoreapp3.1 文件夹中生成一个名为 MyClass.cs 的文件,其中包含 class 和 属性 和一个方法。如您所见,名称和类型在下面的代码中设置。
Microsoft 对此有很好的文档:there's a page 还展示了如何编译和运行 以这种方式生成的代码。
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;
}
}
}