如何以编程方式将属性插入到.cs源文件中的类中

本文关键字:cs 源文件 插入 属性 编程 方式 | 更新日期: 2023-09-27 18:04:18

我正在创建一个用于向现有类的源代码插入属性的自动化工具。例如:我有一个像这样的现有源代码:

public class MyClass 
{
   //class members goes here
}

我想把它修改成这样

public class MyClass 
{
   //class members goes here
   public string MyProp { get; set; }
}

并保存到同一个文件。

类名、属性类型和属性名是预先知道的,可以作为操作的参数。有什么简单的方法吗?也许regex替换将为此工作,但我不知道使用哪个表达式将是灵活的,无论源代码的新行,空白和标识策略。

EDIT:我正在寻找的只是自动生成源代码,而不是在运行时操作类

如何以编程方式将属性插入到.cs源文件中的类中

一种干净的方法是使用T4模板生成部分类。

T4模板是在编译时生成代码的好方法。

这些生成的文件不应该被开发人员修改,相反,开发人员创建另一个文件,其中包含部分类成员的附加定义。

这样,您就可以一次又一次地调整和运行生成器,而不会扰乱自定义代码。

下面使用正则表达式的方法应该可以工作,尽管我不认为这可能是做您需要的事情的最佳方法。不太清楚,那要看你的需求了。我一直这样做(创建修改.cs文件的脚本,或从 notepad++ 创建宏)。也许您还想看看部分类

string text = 
@"namespace X {
    public class MyClass {
        //Text here
    }
}";
string className = "MyClass";
string propertyType = "string";
string propertyName = "MyProperty";
string regex = string.Format(@"( *)((public?)'s*(static)?'s*class's+{0}'s*{{)", className);
string replacement = string.Format("$1$2'r'n'r'n$1    public {0} {1} {{ get; set; }}", propertyType, propertyName);
var modified = Regex.Replace(text, regex, replacement);
Console.WriteLine(modified);

上面的代码将打印:

namespace X {
    public class MyClass {
        public string MyProperty { get; set; }
        //Text here
    }
}

Edit:可以看到,它正确地缩进了代码。它使用包含类定义的行中相同数量的空格+ 4。如果你想添加一个选项卡,或者其他什么,你可以改变正则表达式

用于在运行时添加

程序集不能在运行时更改,所以您需要在运行时生成一个DLL并加载它,或者您可以使用这个问题中所描述的ExpandoObject

用于在编译时添加

如果您不想在运行时添加代码,那么您需要查找CodeDom

添加运行时间和编译时间

只是想加入另一个选项。虽然在很多方面你都不想这么做,但至少从你提供的那一点信息来看。

你可以使用IL编织。这个选项发生在编译之后(到MSIL),但是在运行之前。其结果是,您的类获得了编译时操作的所有好处,但提供了比CodeDom所能提供的更多信息。

MSIL编织的实现包括PostSharp。Net(商业产品)和Mono。Cecil(注意:不要让Mono部分欺骗了你,它也可以在。net上工作)。

的优势包括:

  • 它(运行时)和编译时方法一样快
  • 你有很多CodeDom丢失的信息(部分类是CodeDom中一个特别痛苦的问题)

缺点包括:

  • 编织是困难的(你甚至失去了编译时的检查)
  • IDE对编织的支持非常少

您可以尝试用Ruby编写的通用代码生成器cog。Cog有一个嵌入特性,这将非常适合您的目的。要实现您的目标,您可以这样修改您的类

public class MyClass 
{
    // class members goes here
    // cog: auto-properties
}

然后写一个齿轮生成器(一个简短的ruby脚本),像这样

embed 'auto-properties' do |c|
    "    /* whatever you return gets injected into #{c.filename} */"
end

在本例中,c是EmbedContext的一个实例。设置好生成器后,使用命令行调用

来运行它。
$ cog gen
Updated src/MyClass.cs - 1st occurrence of embed 'auto-properties'

现在你的类看起来像这样

public class MyClass 
{
    // class members goes here
// cog: auto-properties {
    /* whatever you return gets injected into MyClass.cs */
// cog: }
}

如何生成给定文件名的属性取决于您。cog非常灵活,还支持使用ERB模板生成代码。