T4 CustomHost 错误空路径 System.IO.FileStream.Init

T4 CustomHost error Empty path System.IO.FileStream.Init

正在尝试使用来自 here 的 T4 自定义主机,并根据产生的错误对其进行了调整,并在底部提出了代码。尝试像这样使用自定义主机时...

    var host = new CustomHost
    {
        TemplateFile = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "SimpleDate.tt"),
        CurrentAppDomain = AppDomain.CurrentDomain
    };

    var output = new Engine().ProcessTemplate(File.ReadAllText(host.TemplateFile), host);

    if (host.Errors.HasErrors) throw new Exception(host.Errors[0].ErrorText);

...它returns以下错误...

System.Exception
  HResult=0x80131500
  Message=An exception was thrown while trying to compile the transformation code. The following Exception was thrown:
System.ArgumentException: Empty path name is not legal.
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
   at Roslyn.Utilities.FileUtilities.OpenFileStream(String path)
   at Microsoft.CodeAnalysis.MetadataReference.CreateFromFile(String path, MetadataReferenceProperties properties, DocumentationProvider documentation)
   at Microsoft.VisualStudio.TextTemplating.CompilerBridge.<>c.<.ctor>b__15_0(String x)
   at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
   at System.Linq.Enumerable.<UnionIterator>d__67`1.MoveNext()
   at System.Linq.Enumerable.<UnionIterator>d__67`1.MoveNext()
   at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
   at System.Collections.Immutable.ImmutableArray.CreateRange[T](IEnumerable`1 items)
   at Microsoft.CodeAnalysis.ImmutableArrayExtensions.AsImmutableOrEmpty[T](IEnumerable`1 items)
   at Microsoft.CodeAnalysis.Compilation.ValidateReferences[T](IEnumerable`1 references)
   at Microsoft.CodeAnalysis.CSharp.CSharpCompilation.WithReferences(IEnumerable`1 references)
   at Microsoft.CodeAnalysis.CSharp.CSharpCompilation.CommonWithReferences(IEnumerable`1 newReferences)
   at Microsoft.VisualStudio.TextTemplating.CompilerBridge.PrepareNewCompilation()
   at Microsoft.VisualStudio.TextTemplating.CompilerBridge.Compile()
   at Microsoft.VisualStudio.TextTemplating.TransformationRunner.Compile(String source, String inputFile, IEnumerable`1 references, Boolean debug, SupportedLanguage language, String compilerOptions)

我不确定这个错误试图告诉我什么。提供了一个有内容的模板文件,非常简单,只在一个文本文件中产生一个日期。在 VS 项目中包含模板会生成文本文件,因此模板有效。谁能告诉我我做错了什么?我的 CustomHost 有问题吗?

using System;
using System.IO;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Text;
using Microsoft.VisualStudio.TextTemplating;
using System.Diagnostics;
using System.Linq;

namespace TTPlay
{
    public class CustomHost : ITextTemplatingEngineHost
    {
        public string TemplateFile { get; set; }
        public string FileExtension { get; set; } = ".txt";
        public Encoding FileEncoding { get; set; } = Encoding.UTF8;

        public IList<string> StandardAssemblyReferences { get; set; } = new string[]
        {
            typeof(System.Uri).Assembly.Location,
        };

        public IList<string> StandardImports { get; set; } = new List<string>
        {
            "System",
            "System.IO.FileSystem",
        };

        public bool LoadIncludeText(string requestFileName, out string content, out string location)
        {
            content = System.String.Empty;
            location = System.String.Empty;

            if (File.Exists(requestFileName))
            {
                content = File.ReadAllText(requestFileName);
                return true;
            }
            else
            {
                return false;
            }
        }

        public object GetHostOption(string optionName)
        {
            object returnObject;
            switch (optionName)
            {
                case "CacheAssemblies":
                    returnObject = true;
                    break;
                default:
                    returnObject = null;
                    break;
            }
            return returnObject;
        }

        public string ResolveAssemblyReference(string assemblyReference)
        {
            if (File.Exists(assemblyReference))
            {
                return assemblyReference;
            }

            string candidate = Path.Combine(Path.GetDirectoryName(this.TemplateFile), assemblyReference);
            if (File.Exists(candidate))
            {
                return candidate;
            }

            return "";
        }

        public Type ResolveDirectiveProcessor(string processorName)
        {
            if (string.Compare(processorName, "XYZ", StringComparison.OrdinalIgnoreCase) == 0)
            {
                //return typeof();
            }
            throw new Exception("Directive Processor not found");
        }

        public string ResolvePath(string fileName)
        {
            if (fileName == null) { throw new ArgumentNullException("the file name cannot be null"); }

            if (File.Exists(fileName)) { return fileName; }

            if (!string.IsNullOrWhiteSpace(this.TemplateFile))
            {
                string candidate = Path.Combine(Path.GetDirectoryName(this.TemplateFile), fileName);
                if (File.Exists(candidate))
                {
                    return candidate;
                }
            }

            return fileName;
        }

        public string ResolveParameterValue(string directiveId, string processorName, string parameterName)
        {
            if (directiveId == null)
            {
                throw new ArgumentNullException("the directiveId cannot be null");
            }
            if (processorName == null)
            {
                throw new ArgumentNullException("the processorName cannot be null");
            }
            if (parameterName == null)
            {
                throw new ArgumentNullException("the parameterName cannot be null");
            }

            return String.Empty;
        }

        public void SetFileExtension(string extension) => FileExtension = extension;
        public void SetOutputEncoding(Encoding encoding, bool fromOutputDirective) => FileEncoding = encoding;
        public void LogErrors(CompilerErrorCollection errors) => this.Errors = errors;
        public CompilerErrorCollection Errors { get; set; }
        public AppDomain ProvideTemplatingAppDomain(string content) => CurrentAppDomain;

        private AppDomain _currentAppDomain = null;
        public AppDomain CurrentAppDomain
        {
            get => _currentAppDomain;
            set
            {
                _currentAppDomain = value;

                // get assembly directories
                foreach (var assembly in _currentAppDomain.GetAssemblies())
                {
                    var directory = System.IO.Path.GetDirectoryName(assembly.Location);
                    if (!AssemblyDirectories.Any(x => x.FullName == directory))
                    {
                        AssemblyDirectories.Add(new DirectoryInfo(directory));
                    }
                }
            }
        }

        public List<DirectoryInfo> AssemblyDirectories = new List<DirectoryInfo>();
    }
}

[捂脸] 结果证明我犯了一个相当简单的错误。从标准导入中删除 System.IO.FileSystem 引用并将其添加到标准程序集引用中(不要忘记添加 dll 扩展名)。现在运行...

    public IList<string> StandardAssemblyReferences { get; set; } = new string[]
    {
        typeof(System.Uri).Assembly.Location,
        "System.IO.FileSystem.dll",
    };

    public IList<string> StandardImports { get; set; } = new List<string>
    {
        "System",
    };