C#预处理工具存在吗?

7
有没有什么工具可以预处理C#源文件而不编译它,类似于在GCC中使用-E标志的方式?我尝试了使用GCC-它成功地处理了#if指令,但是它会卡在任何#region指令上...
理想情况下,我希望能够运行该工具来删除任何求值为false的#if块,并可选择标记是否删除/保留注释、#region、#pragma指令等。
为了把这个问题放到上下文中,我想要发布一些源代码,这些代码是一个(更大)项目的一部分,同时删除只与更大项目相关的部分。例如,有些代码块看起来像这样:
#if (SUBPROJECT)
namespace SubProject
#else
namespace CompleteProject
#endif
{
  public class SomeClass()
  {
#if (!SUBPROJECT)
    // This might call a method contained in an assembly that potentially 
    // won't be available to the sub-project, or maybe a method that hooks
    // into a C library via P/Invoke...
    string result = CallSomeCleverMethod();
#else
    // This might call a method that performs a simplified version of the 
    // above, but does so without the above's assembly or P/Invoke 
    // dependencies...
    string result = CallSomeSimpleMethod();
#endif
  }
}

请记住,我这里不是在进行构建 - 这纯粹是关于只发布更大项目源代码的子集。任何想法/帮助都会受到赞赏。
5个回答

5

使用GNU C预处理器(cpp)直接处理源文件(而不是通过gcc)可以提供更多对输出的控制。通过这种方式,我能够以适当的方式处理源文件...

这里有一个例子:

cpp -C -P -DSUBPROJECT Input.cs Output.cs

我曾尝试使用Visual Studio提供的C/C++编译器来做类似的事情,但一段时间后放弃了...


1
我可以在哪里获取可执行文件? - NightOwl888
它是GNU编译器集合的一部分 - 如果您正在运行OS X或Linux,则可能已经安装了它。如果您正在运行Windows,则可能需要MinGW。 - Mark Beaton
我在这里找到了一个可用的:http://mcpp.sourceforge.net/download.html,但可执行文件是mccp而不是cpp。 - NightOwl888
1
很遗憾,输出文件中有空行。有什么方法可以避免它吗? - Ayyappa

3
我不相信csc或msc(mono编译器)有任何标志可以输出预处理的文件。
如果我必须这样做,并且它是一个小的子集,我会编译,然后使用Reflector反编译回C#并导出文件。 如果您有很多文件,则有一个Reflector Add-In称为FileGenerator for Reflector
不幸的是,这不会是您代码库的真实副本--它将重新格式化所有代码,并且您将失去所有注释。

2
我不知道有没有C#的预处理器可以让你在不构建代码的情况下导出源代码的子集。
但是,你可以通过使用代码生成模板来实现相同的效果。只需将预处理指令更改为适当的模板等效指令即可。
Visual Studio 2008内置了一个名为T4的代码生成工具。还有其他第三方选项,如CodesmithTools或免费的MyGeneration.Net

1
听起来很有前途 - 我之前没有考虑过T4 - 我会研究一下并尽快回报。 - Mark Beaton

1

我曾经遇到过这种情况——需要清理旧项目中的某些过时的C#预处理分支,同时保留相关分支。内置的C预处理器无法帮我完成此任务,因为其输出文件从不包含预处理指令。当然,有一些C处理器工具,例如unifdefcoan可以部分地删除C/C++中过时的分支。但问题在于它们并不完全支持C#语法,例如#region和#pragma。因此,我不得不为我的任务编写自己的Python工具undefine。我使用正则表达式来解析指令,使用sympy库来简化和计算逻辑表达式。要解决您的问题,请尝试以下操作:

>>python undefine apply -d SUBPROJECT your_project_path

这个工具在我的大约10百万行的代码库中表现良好。

1

也许更容易、更符合C#的语法,是创建接口并有不同的接口实现?一组接口实现可以作为库打包并重新分发。


我需要能够处理实际的类/命名空间名称、元数据(自定义属性等)-请参见问题中的命名空间示例。我也不想在不必要的情况下增加实现复杂性。 - Mark Beaton
2
你觉得上面的代码已经很复杂了吗?我还是认为你对此持有C++的思维方式,可能忽略了一些C#提供的工具,但祝你好运,希望能找到让你满意的解决方案! - Brian Sullivan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接