.net T4文本模板-是否可以从主机获取编译符号?

.net T4文本模板-是否可以从主机获取编译符号?,.net,visual-studio-2010,t4,.net,Visual Studio 2010,T4,背景: 我有一个用C#编写的开源游戏库,它使用了不安全的代码、指针算法等,对性能进行了高度调优。我最近将该库移植到了Windows Phone。不幸的是,Windows Phone根本不支持不安全的代码,因此我不得不在源代码中添加如下预处理器指令: #if WINDOWS || XBOX public unsafe struct Foo #elif WINDOWS_PHONE public struct Foo #endif 由于这些指令的数量太多,代码库变得很难阅读和维护,因此我一直在探索其

背景:

我有一个用C#编写的开源游戏库,它使用了不安全的代码、指针算法等,对性能进行了高度调优。我最近将该库移植到了Windows Phone。不幸的是,Windows Phone根本不支持不安全的代码,因此我不得不在源代码中添加如下预处理器指令:

#if WINDOWS || XBOX
public unsafe struct Foo
#elif WINDOWS_PHONE
public struct Foo
#endif
由于这些指令的数量太多,代码库变得很难阅读和维护,因此我一直在探索其他选项——其中之一是使用T4的文本模板

问题:

在走T4路线之前,我需要知道的是,是否可以从文本模板中获取编译符号?我已经研究了模板参数,但从外部修改它们似乎并不容易。理想情况下,我希望看到的是有点像这样的东西:

<# if (Host.CompilationSymbols.Contains("WINDOWS_PHONE") { #>
public struct Foo
<# { #>

公共结构Foo
如果有人能告诉我这是否可能,我将不胜感激

马特, 它们不可用,因为从VS2010开始,项目的编译和模板的编译是完全隔离的

然而,我有一个(有点笨拙的)解决方法给你

如果包含包含模板指令的存根文件,则可以使用适当的编译符号设置编译器选项

e、 g.包含以下内容的简单存根,名为Define.t4:

<#@ template compilerOptions="/d:XBOX" debug="false" hostspecific="false" language="C#" #>

把它放在一个名为XBOX的子目录中,把一个类似的子目录放在一个名为PHONE的目录中

<#@ template compilerOptions="/d:PHONE" debug="false" hostspecific="false" language="C#" #>

请注意编译器符号定义

现在设置一个环境变量为XBOX或PHONE,比如说架构

现在,不要在模板中使用template指令,而是包含Define.t4文件,这样您就可以使用常规的C#/VB条件语法。别忘了把“如果”放在他们自己的线上。下面是一个例子:

<#@ include file="$(ProjectDir)%ARCHITECTURE%\Define.t4" #>
<#@ output extension=".txt" #>
<#
#if XBOX #>
public unsafe struct Foo
<#
#else #>
public struct Foo
<#
#endif #>

公共不安全结构Foo
公共结构Foo

希望这能让你动起来。

谢谢你,加雷斯!我有一个变通方法,从模板中解析.csproj文件并查找节点,但您的方法要干净得多:)注意:目前Microsoft.VisualStudio.TextTemplating 15.0中似乎存在缺陷,这意味着“编译器选项”中定义的预处理器符号在模板指令中,没有通过TextTemplating CompilerBridge传递给编译器请参见:好奇-假设您使用T4删除不安全声明属性,您如何处理实际的不安全代码?显然,这不是模板更改内容的唯一地方-其他示例包括Foo*bar更改为ref Foo bar,或bar->foo()更改为bar.foo()