2016-08-17 132 views
0

在t4文本模板中,我试图加载一个dll文件:Assembly.LoadFile(dllPath)

但它返回错误:绝对路径信息是必需的

该dll路径是:var dllPath = "$(TargetDir)Project.dll"$(SolutionDir)Project\\bin\\debug\\Project.dll

我怎样才能变换“$(TARGETDIR)Project.dll”在他的真正形成"C:\Users\....\Project.dll"之前将其发送到Assembly.LoadFile

回答

1

在T4中,我使用ttinclude来禁用覆盖结果,只允许它在使用名为“RegenCodeFiles”的特定命名解决方案配置时继续生成代码。

有几种不同的方法可以解决这个问题,您可能会发现有用的,以及一个程序集解析器,通过包文件夹(它的硬编码,应该寻找nuget.config)来查看。

我会告诫的一件事(仅因为它的一个麻烦的工作流程)试图引用TT中的一部分TT。

的包括被称为像这样...

<#@ template debug="true" hostspecific="true" language="C#" #> 
<#@ include file="CodeGenHelpers.ttinclude" #> 
var regenHelper = new CodeGenHelpers(Host); 
regenHelper.SetupBinPathAssemblyResolution(); 

if (regenHelper.ShouldRegenerate() == false) 
{ 
    Debug.WriteLine($"Not Regenerating File"); 
    var existingFileName = Path.ChangeExtension(Host.TemplateFile, "cs"); 
    var fileContent = File.ReadAllText(existingFileName); 
    return fileContent; 
} 

Debug.WriteLine($"Regenerating File"); 
// ...rest of T4 

CodeGenHelpers.ttinclude

<#@ assembly name="Microsoft.VisualStudio.Shell.Interop.8.0" #> 
<#@ assembly Name="EnvDTE" #> 
<#@ import namespace="System.IO" #> 
<#@ import namespace="System.Reflection" #> 
<#@ import namespace="System.Diagnostics" #> 
<#@ import namespace="EnvDTE" #> 
<#@ import namespace="Microsoft.VisualStudio.Shell.Interop" #> 
<#@ import namespace="Microsoft.VisualStudio.TextTemplating" #> 
<#+ 

    public class CodeGenHelpers 
    { 
     private static string _ConfigName; 
     private static bool? _ShouldRegenerate; 
     private ITextTemplatingEngineHost _Host; 
     private static DTE _Dte; 

     public CodeGenHelpers(ITextTemplatingEngineHost host) 
     { 
      _Host = host; 
     } 

     public bool ShouldRegenerate() 
     { 
      if (_ShouldRegenerate.HasValue == false) 
      { 
       var configName = GetConfigName(); 
       _ShouldRegenerate = "RegenCodeFiles".Equals(configName, StringComparison.OrdinalIgnoreCase); 
      } 

      return _ShouldRegenerate.Value; 
     } 

     public string GetConfigName() 
     { 
      if (string.IsNullOrWhiteSpace(_ConfigName)) 
      { 
       _ConfigName = GetDte().Solution.SolutionBuild.ActiveConfiguration.Name; 
      } 
      return _ConfigName; 
     } 

     public DTE GetDte() 
     { 
      if (_Dte == null) 
      { 
       var serviceProvider = _Host as IServiceProvider; 
       _Dte = serviceProvider.GetService(typeof(SDTE)) as DTE; 
      } 
      return _Dte; 
     } 

     public void SetupBinPathAssemblyResolution() 
     { 
      AppDomain.CurrentDomain.AssemblyResolve += ResolveMeh; 
     } 

     //load from nuget packages first 
     public Assembly ResolveMeh(object sender, ResolveEventArgs args) 
     { 
      var currentFolder = new FileInfo(_Host.ResolvePath(_Host.TemplateFile)).DirectoryName; 
      var configName = GetConfigName(); 
      //probably look at the project properties in DTE, but whatever 
      var d = _Dte; 
      var assemblyName = new AssemblyName(args.Name).Name + ".dll"; 
      var assemblyLoadFolder = Path.Combine(currentFolder, $"bin\\{configName}"); 
      var assemblyPath = Path.Combine(assemblyLoadFolder, assemblyName); 
      if (System.IO.File.Exists(assemblyPath) == true) 
      { 
       var assembly = Assembly.LoadFrom(assemblyPath); 
       return assembly; 
      } 

      //there are nuget services for vs, but they are installed via nuget package, 
      // which is what this is looking for so I dont know if it will work. 
      // https://www.nuget.org/packages/NuGet.VisualStudio 


      var solutionFilePath = GetDte().FullName; 
      var solutionFile = GetDte().FileName; 
      var solutionFolder = solutionFilePath.Replace(solutionFile, string.Empty); 
      var packagesFolder = System.IO.Path.Combine(solutionFolder, "packages"); 
      var files = System.IO.Directory.GetFiles(packagesFolder, assemblyName, SearchOption.AllDirectories); 
      if (files.Length > 0) 
      { 
       var assembly = Assembly.LoadFrom(files[0]); //prob also check target fw 
       return assembly; 
      } 

      return null; 
     } 

    } 

#> 
+0

感谢您的帮助。 @Erick为什么你还没有标记这个正确的呢? –