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",
};
正在尝试使用来自 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",
};