【问题标题】:How can I get the real Path from a Macro Path like $(TargetDir)?如何从像 $(TargetDir) 这样的宏路径中获取真正的路径?
【发布时间】:2016-08-17 05:28:19
【问题描述】:

在 t4 文本模板中,我尝试使用:Assembly.LoadFile(dllPath) 加载 dll。

但它返回错误:需要绝对路径信息

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

我怎样才能将 "$(TargetDir)Project.dll" 转换成他的真实形式"C:\Users\....\Project.dll",然后再发送到Assembly.LoadFile

【问题讨论】:

    标签: c# reflection path t4


    【解决方案1】:

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

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

    我要提醒注意的一件事(只是因为它是一个麻烦的工作流程)是试图在 TT 中引用 TT 所属的程序集。

    include 是这样调用的...

    <#@ 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;
            }
    
        }
    
    #>
    

    【讨论】:

    • 感谢您的帮助。 @Erick 你为什么还没有标记这个正确呢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-20
    • 1970-01-01
    • 2011-12-12
    • 2020-03-14
    • 1970-01-01
    相关资源
    最近更新 更多