如何在T4模板中定义相对于模板文件的程序集指令路径?
解决T4模板中基于自身路径引用程序集的问题
我之前也碰到过完全一样的场景——共享T4模板被不同层级的项目和解决方案引用,$(ProjectDir)或$(SolutionDir)这类宏根本用不了,必须靠模板自身的路径来定位程序集。下面是我验证过的可靠解决方案:
核心思路
利用T4内置的Host对象(实现ITextTemplatingEngineHost接口)获取共享模板自身的完整路径,结合System.IO.Path类拼接出程序集的绝对路径,最后动态加载程序集,彻底摆脱对引用模板所在层级的依赖。
具体步骤(以共享模板SharedTemplate.ttinclude为例)
1. 导入必要的依赖
首先在共享模板顶部添加这些指令,确保能使用路径处理和Host对象的功能:
<#@ assembly name="System.Core" #> <#@ import namespace="System.IO" #>
2. 获取共享模板自身的目录
不管主模板在项目结构的哪一层,只要它能正确include共享模板,我们就能通过Host.ResolvePath获取到共享模板的绝对路径,进而得到它所在的目录:
<# // 这里要填共享模板的实际文件名(包括后缀) string sharedTemplateName = "SharedTemplate.ttinclude"; // 解析出共享模板的完整路径 string sharedTemplateFullPath = Host.ResolvePath(sharedTemplateName); // 获取模板所在的目录 string sharedTemplateDir = Path.GetDirectoryName(sharedTemplateFullPath); #>
3. 拼接程序集的绝对路径
假设你的程序集位于共享模板目录的../Lib/MyBusinessLogic.dll(根据实际目录结构调整相对路径),用Path.Combine和Path.GetFullPath确保路径正确(自动处理../这类相对标识):
<# // 替换成你的程序集相对路径 string assemblyRelativePath = @"../Lib/MyBusinessLogic.dll"; string assemblyFullPath = Path.GetFullPath(Path.Combine(sharedTemplateDir, assemblyRelativePath)); #>
4. 动态加载程序集
不用传统的<#@ assembly #>指令,而是用Host.LoadAssembly方法加载程序集,这样就能确保路径是基于共享模板自身的:
<# Host.LoadAssembly(assemblyFullPath); #>
为什么这个方案可靠?
- 不管主模板在项目结构的哪一层,只要它能正确引用共享模板,
Host.ResolvePath就能准确找到共享模板的位置。 Path.GetFullPath会自动处理相对路径中的../或./,生成标准的绝对路径,避免路径错误。- 兼容Visual Studio内的T4运行和外部的
TextTransform.exe工具。
额外提示
如果需要引用多个程序集,可以把路径拼接和加载的逻辑封装成一个小方法,放在共享模板里复用,比如:
<# void LoadAssemblyRelativeToSharedTemplate(string relativePath) { string sharedTemplateName = "SharedTemplate.ttinclude"; string sharedTemplateFullPath = Host.ResolvePath(sharedTemplateName); string sharedTemplateDir = Path.GetDirectoryName(sharedTemplateFullPath); string assemblyFullPath = Path.GetFullPath(Path.Combine(sharedTemplateDir, relativePath)); Host.LoadAssembly(assemblyFullPath); } // 调用加载多个程序集 LoadAssemblyRelativeToSharedTemplate(@"../Lib/MyBusinessLogic.dll"); LoadAssemblyRelativeToSharedTemplate(@"../Lib/MyDataAccess.dll"); #>
内容的提问来源于stack exchange,提问作者rm5432
相关产品推荐
相关产品推荐

