将 T4 模板与 VS2010 Express 和 XNA 配合使用
本文关键字:XNA Express T4 VS2010 | 更新日期: 2023-09-27 17:56:11
我正在使用VS2010 express创建一个用xna构建的游戏。我正在尝试使用 t4 模板(生成内容位置的强类型类,因此使用 Level1Location = Content.Levels.Level1
而不是 Level1Location = @"Content'Levels'Level1"
.
我读过 T4 模板在速成版中没有正确设置,但如果我创建一个扩展名为 .tt 的文件,它应该可以工作。但是,当我在 XNA 类库中创建一个 .tt 文件时,我收到以下警告(并且没有代码文件):
The custom tool 'TextTemplatingFileGenerator' failed. Could not load file or assembly 'Microsoft.VisualStudio.ServicesProxy, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.
我搜索了又搜索,找不到任何有用的东西。以前有人遇到过这个问题吗?有人知道是否有解决方案吗?
我还尝试按照建议将自定义工具更改为TextTemplatingFilePreprocessor
,但是我遇到了相同的错误。
编辑:我发现问题是它在XNA项目/库中。它在普通类中工作正常,所以我的解决方法是将项目添加到解决方案中,仅用于模板。不过,问题仍然悬而未决,你能让它在 XNA 项目中工作吗?
虽然我已经发布了这个答案,但我仍然在寻找一种更简单的方法(即 XNA 项目中的 tt 文件本身)
如果有人找到此页面,这是我的解决方法:
创建新的(非 XNA)类库项目。
添加一个文本文件,使用 .tt 扩展名重命名。
编写 T4 代码(见下文)。
在 XNA 项目中,添加现有项,导航到创建的.cs文件,然后添加为链接。
然后,为了确保我们始终拥有更新的 cs 文件,请右键单击 XNA 项目并单击项目依赖项,然后勾选包含 .tt 文件的类库项目。
使用下面的模板代码,您可以执行诸如Content.Load(Content.MyGameContent.Graphics.Textures.AwesomeTexture)之类的操作;例如,您还可以使用Content.MyGameContent.Graphics.Textures将文件夹名称作为字符串获取,这要归功于时髦的隐式字符串转换运算符。
<#@ template language="c#" hostspecific="true" #>
<#@ assembly name="EnvDTE100" #>
<#@ assembly name="EnvDTE" #>
<#@ assembly name="System" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="EnvDTE100" #>
<#@ import namespace="EnvDTE" #>
<#@ import namespace="System" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Collections.Generic" #>
namespace Content
{
<#
var serviceProvider = this.Host as IServiceProvider;
var dte = serviceProvider.GetService(typeof(DTE)) as DTE;
foreach (Project Proj in dte.Solution.Projects)
{
bool IsContentProj = false;
foreach(Property Prop in Proj.Properties)
{
if(Prop.Name == "Microsoft.Xna.GameStudio.ContentProject.ContentRootDirectoryExtender.ContentRootDirectory")
{
IsContentProj = true;
}
}
if (IsContentProj)
{
#>
public static class <#=Proj.Name #>
{
<#
foreach(ProjectItem PI in Proj.ProjectItems)
{
GenerateProjectItemClass(PI, true, " ");
}
#>
}
<#
}
}
#>
}
<#+
void GenerateProjectItemClass(ProjectItem Item, bool Static, string Indent)
{
const string FolderItemKind = "{6BB5F8EF-4483-11D3-8BCF-00C04F8EC28C}";
const string FileItemKind = "{6BB5F8EE-4483-11D3-8BCF-00C04F8EC28C}";
string ClassName = Path.GetDirectoryName(Item.FileNames[0]).Substring(Path.GetDirectoryName(Item.FileNames[0]).LastIndexOf(Path.DirectorySeparatorChar) + 1);
int ContentRootLength = Path.GetDirectoryName(Item.ContainingProject.FileName).Length;
string RelativeLocation = Path.ChangeExtension(Path.GetFullPath(Item.FileNames[0]).Substring(ContentRootLength + 1), null);
switch(Item.Kind)
{
case FolderItemKind:
#>
<#=Indent#>public class <#=ClassName #>Class
<#=Indent#>{
<#=Indent#> private const string Location = @"<#= RelativeLocation #>";
<#=Indent#> public static implicit operator string(<#=ClassName #>Class MyClass)
<#=Indent#> {
<#=Indent#> return Location;
<#=Indent#> }
<#+
foreach(ProjectItem ChildItem in Item.ProjectItems)
GenerateProjectItemClass(ChildItem, false, Indent + " ");
#>
<#=Indent#>}
<#=Indent#>
<#=Indent#>public <#= Static ? "static " : " " #><#=ClassName#>Class <#=ClassName#> = new <#=ClassName#>Class();
<#=Indent#>
<#+
break;
case FileItemKind:
#>
<#=Indent#>public <#= Static ? "static " : " " #>string <#= Path.GetFileNameWithoutExtension(Item.FileNames[0]) #> = @"<#=RelativeLocation #>";
<#+
break;
}
}
#>