如何在T4模板中输出命名空间?

31

我有一个T4模板,用TextTemplatingFileGenerator自定义工具在Visual Studio中设置了一个类:

<#@ template language="C#v3.5" hostspecific="True" debug="True" #>
<#
  var className = System.IO.Path.GetFileNameWithoutExtension(Host.TemplateFile);
  var namespaceName = "MyNamespace";
#>

namespace <#= namespaceName #>
{
    public static class <#= className #>
    {
        // some generated code
    }
}

我该如何获取在Visual Studio中的“自定义工具命名空间”属性值,以便不必硬编码命名空间?

甚至可以使用C#项目的默认命名空间。

6个回答

49

如果您使用的是Visual Studio 2010,则可以通过检查CallContext的"NamespaceHint"属性来检索命名空间。

System.Runtime.Remoting.Messaging.CallContext.LogicalGetData("NamespaceHint");

2
不幸的是,当使用基于MSBuild的转换系统时,这个技巧不起作用(如此处所示:http://www.olegsych.com/2010/04/understanding-t4-msbuild-integration/)。糟糕。 :( - Brad Wilson
此函数导致调试失败。 - johnny 5
@BradWilson 这个链接似乎已经失效了。 - Venkat
@Venkat,现在我认为作为社区成员,你和我们其他人一样都可以使用搜索引擎并提供任何更加更新的信息。 - GarethJ
1
Brad提到的文章可以在这里查看: https://web.archive.org/web/20130805044018/http://www.olegsych.com:80/2010/04/understanding-t4-msbuild-integration/ - Glaerferyn
显示剩余2条评论

15

以下是您可以使用T4工具箱实现的功能:

<#@ template language="C#v3.5" hostspecific="True" debug="True" #> 
<#@ include file="T4Toolbox.tt" #>
<# 
  var namespaceName = TransformationContext.DefaultNamespace; 
#> 
TransformationContext类的DefaultNamespace属性返回一个字符串,该字符串基于项目的根命名空间和.tt文件在其中的位置而确定(即将文件夹视为命名空间)。这样,您就不必为每个.tt文件的每个实例指定Custom Tool Namespace属性。
如果您喜欢使用Custom Tool Namespace属性,您可以将Host.TemplateFile传递给@sixlettervariables发布的GetCustomToolNamespace方法。

我收到了错误信息:“T4Toolbox.TransformationContext”不包含“DefaultNamespace”的定义。 - Thomas Stock
1
在您的这篇文章中找到了解决方法: http://www.olegsych.com/2012/12/t4-toolbox-for-visual-studio-2012/ - Thomas Stock
那篇帖子现在已经消失了,但是DefaultNamespace似乎现在在T4Toolbox.ClrTemplate类中。 (尽管整个项目需要更新为VS 2019) - Ann L.

8

Damien Guard在博客文章中包含了一些代码,用于检索给定文件的自定义工具命名空间

public override String GetCustomToolNamespace(string fileName)
{
    return dte.Solution.FindProjectItem(fileName).Properties.Item("CustomToolNamespace").Value.ToString();
}

6
我是如何做到这一点的:

我的做法:

<#@ assembly name="EnvDTE" #>
<#@ import namespace="EnvDTE" #>

<# 
    // Get value of 'Custom Tool Namespace'
    var serviceProvider = (IServiceProvider)this.Host;
    var dte = (DTE)serviceProvider.GetService(typeof(DTE));    
    var Namespace = dte.Solution.FindProjectItem(this.Host.TemplateFile).Properties.Item("CustomToolNamespace").Value;
 #>

namespace <#= Namespace #> {

}

对我有用;将“CustomToolNamespace”替换为“DefaultNamespace”。 - bernhof

2
如果您使用的是Visual Studio 2012
EdmItemCollection ItemCollection = loader.CreateEdmItemCollection(inputFile);
string namespaceName = System.Runtime.Remoting.Messaging.CallContext.LogicalGetData("NamespaceHint").ToString();

EntityFrameworkTemplateFileManager fileManager = EntityFrameworkTemplateFileManager.Create(this);

Aldo Flores @alduar


0

被接受的答案在Visual Basic项目上不起作用。我不得不使用来自以下方法:http://lennybacon.com/post/2010/12/10/generatingcodefileswithcorrectnamespacesusingt4

var hostServiceProvider = (IServiceProvider)Host;
var dte = (EnvDTE.DTE)hostServiceProvider.GetService(typeof(EnvDTE.DTE));
var activeSolutionProjects = (Array)dte.ActiveSolutionProjects;
var dteProject = (EnvDTE.Project)activeSolutionProjects.GetValue(0);
var defaultNamespace = dteProject.Properties.Item("DefaultNamespace").Value;

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