5

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

public class MyClass 
{
   //class members goes here

}

我想修改成这样

public class MyClass 
{
   //class members goes here

   public string MyProp { get; set; }
}

并将其保存到同一个文件中。

类名、属性类型和属性名将是事先知道的,并且可以被视为操作的参数。知道如何轻松做到这一点吗?也许正则表达式替换会为此工作,但我不知道无论源代码的新行、空格和标识策略如何,使用哪个表达式将是灵活的。

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

4

5 回答 5

5

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

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

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

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

于 2013-03-18T06:33:15.247 回答
3

以下使用正则表达式的方法应该可以工作,尽管我认为这可能不是满足您需要的最佳方法。真的不知道,这取决于你的需求。我一直这样做(要么创建修改文件的脚本,要么来自Notepad++.cs的宏)。也许您可能还想看看部分类

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
    }
}

编辑:如您所见,它正确缩进了代码。它使用包含类定义的行的相同数量的空格 + 4 个。如果要添加选项卡或其他任何内容,可以更改正则表达式。

于 2013-03-18T06:07:23.747 回答
2

在运行时添加

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

在编译时添加

如果您不想在运行时添加代码而不是您正在寻找CodeDom

于 2013-03-18T05:40:31.240 回答
0

在运行时和编译时之间添加

只是想加入另一种选择。尽管在很多方面您都不想这样做,至少从您提供的少量信息来看。

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

MSIL 编织的实现包括PostSharp.Net(商业产品)和Mono.Cecil(注意不要让 Mono 部分欺骗您,它也适用于 .Net)。

优点包括:

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

缺点包括:

  • 编织很困难(你甚至会失去编译时间检查)
  • 编织的IDE支持很少
于 2013-03-18T06:23:57.077 回答
0

你可以试试cog,一个用 Ruby 编写的通用代码生成器。cog 有一个嵌入功能,可以很好地满足您的目的。为了实现您的目标,您将像这样修改您的课程

public class MyClass 
{
    // class members goes here

    // cog: auto-properties
}

然后像这样编写一个 cog 生成器(一个简短的 ruby​​ 脚本)

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

在示例中,cEmbedContext的一个实例。设置生成器后,您可以使用命令行调用运行它

$ 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 模板生成代码。

于 2013-03-26T12:29:20.873 回答