2016-08-17 134 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爲什麼你還沒有標記這個正確的呢? –