我的解决方案中包含一些项目。我想在我的一个测试项目中创建一些T4模板,以根据另一个项目中的代码生成测试。测试项目有一个项目参考另一个项目。我遇到的问题是我不知道如何获取我需要生成代码的edmx文件的文件路径。
示例(假装这是一个基于ASCII的解决方案资源管理器):
MySolution.sln
-> MyTests.csproj (C:\a\b\c\)
----> GeneratedTests.tt (C:\a\b\c\GeneratedTests.tt)
-> MyDAL.csproj (C:\x\y\z\)
----> MyModel.edmx (C:\x\y\z\MyModel.edmx)
我的GeneratedTests.tt如何利用其项目引用获取MyModel.edmx的文件路径?
答案 0 :(得分:15)
此答案仅适用于Visual Studio中。
设置T4模板的“hostspecific”属性。这使您可以访问Host属性。键入cast Host to IServiceProvider以调用GetService(typeof(DTE))。这使您可以遍历解决方案的内容。
<#@ template language="c#" hostspecific="true" #>
<#@ assembly name="EnvDTE" #>
<#@ import namespace="EnvDTE" #>
These are the projects in this solution:
<#
var serviceProvider = this.Host as IServiceProvider;
var dte = serviceProvider.GetService(typeof(DTE)) as DTE;
foreach (Project p in dte.Solution.Projects)
{
#>
<#=p.Name#> at <#=p.FullName#>
<#
}
#>
另请参阅ITextTemplatingEngineHost interface on MSDN和T4 Architecture by Oleg Synch的示例。
答案 1 :(得分:10)
基于James Close的评论,我能够编写以下模板来调试我的文件路径:
<#@ template language="C#" debug="true" hostspecific="true"#>
<#@ include file="EF.Utility.CS.ttinclude"#><#@
output extension=".txt"#><#
/////////Some standard-ish settings, continue reading on
CodeGenerationTools code = new CodeGenerationTools(this);
MetadataLoader loader = new MetadataLoader(this);
CodeRegion region = new CodeRegion(this, 1);
MetadataTools ef = new MetadataTools(this);
/////////Below are the relevant sections I used for debugging
string solutionsPath = Host.ResolveAssemblyReference("$(SolutionDir)");//Gives you the location of MySolution.sln
string edmxFile = solutionsPath + "MyDAL/MyDAL/MyModel.edmx"; //Note - VS projects usually have a subdir with the same name as the sln, hence the repetition for MyDAL
#>
Does this file exist?
<#
//
if (File.Exists(edmxFile))
{
//Continue.
#>
Yes
<#
}
else
{
#>
No
<#
}
#>
这将生成.txt文件,并且可以非常快速地帮助您调试是否可以找到您的路径。
作为旁注,如果存在无法找到的相对目录路径(例如../App.config
),我发现它有助于将文件(例如test1.txt
)放在每个目录级别,因为我发现Host.ResolvePath
无法通过我的设置在当前程序集之外看到。由于../../App.config
可能会解析为MySolution\App.config
,但../../MyDal/README.txt
将无法解析(因此无法找到该文件),即使这是正确的路径,此警告可能会很快造成混淆。就我所见,上面的代码似乎否定了这个问题。
上述解决方案也可能是解决此问题的方法 - How to use the poco entity generator
答案 2 :(得分:4)
这不起作用。您必须通过路径引用dll(您可以使用Host.ResolvePath
找到它并使用工具箱中的VolatileAssembly
标记以便能够重新编译它而无需重新启动VS)并使用反射来处理模型。
答案 3 :(得分:4)
使用这些行
string path = this.Host.ResolvePath("");
Directory.SetCurrentDirectory(path);
然后使用相对路径获取您的edmx文件 例如,string inputFile = @“.. \ Modal.edmx”;
答案 4 :(得分:1)
您可以将宏用于特殊目录,例如模板中的$(ProjectDir)
,$(SolutionDir)
,也可以读取.sln或.csproj文件以提取其他项目的目录。
答案 5 :(得分:1)
根据Mina和其他人的回答,我提出了这个解决方案。它列出了当前的工作目录,解决方案路径,并使用Mina的技巧来更改活动的工作目录。
<#@ template debug="true" hostspecific="true" language="C#" #>
<#@ output extension=".cs" #>
<#@ import namespace="System.IO" #>
<#@ assembly name="EnvDTE" #>
<#@ import namespace="EnvDTE" #>
<#
string cwd1 = System.IO.Directory.GetCurrentDirectory();
string solutionPath = Host.ResolveAssemblyReference("$(SolutionDir)");
Directory.SetCurrentDirectory(solutionPath);
string cwd2 = System.IO.Directory.GetCurrentDirectory();
#>
// Solutionpath is:<#= solutionPath #>, old cwd: <#= cwd1 #>, new cwd: <#= cwd2 #>