TemplateFileManager генерирует исключение NullReferenceException в режиме TextTemplatingFilePreprocessor - PullRequest
1 голос
/ 01 апреля 2019

Я хочу использовать шаблон T4 для создания нескольких файлов. Поэтому я использую TemplateFileManagerV2.1.ttinclude файл, чтобы сделать это. Он отлично работает в режиме TextTemplatingFileGenerator (время разработки). Я хочу Run-Time Generation, поэтому я изменил режим на TextTemplatingFilePreprocessor. Теперь моя программа выбрасывает NullReferenceException

enter image description here

После дальнейшей отладки я обнаружил, что экземпляр TextTemplate не создается должным образом в режиме TextTemplatingFilePreprocessor.

enter image description here

enter image description here

Вопрос

Как использовать TemplateFileManager в режиме TextTemplatingFilePreprocessor?

код

Template1.tt

<#@ template language="C#" debug="true" hostSpecific="true" #>
<#@ output extension=".cs" #>
<#@ include file="TemplateFileManagerV2.1.ttinclude" #>
<#@ Assembly Name="System.Core" #>
<#@ Assembly Name="System.Windows.Forms" #>
<#@ import namespace="System" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Diagnostics" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Collections" #>
<#@ import namespace="System.Collections.Generic" #> 
<#
   string Greeting = "Hello";
   var manager = TemplateFileManager.Create(this);
   manager.StartNewFile(Path.Combine(Path.GetDirectoryName(this.Host.TemplateFile), "Outputfile2.cs"));
#>
namespace MyNameSpace{
  class MyGeneratedClass{
     static void main (string[] args){
       System.Console.WriteLine("<#= Greeting #>, the time is now: <#= System.DateTime.Now.ToString() #>");
     }
  }
}
<#
    manager.Process();
#>

Код для запуска шаблона T4

var page = new Template1();
var pageContent = page.TransformText();

Решение пробовал

Настройка Host вручную. Теперь Host.AsIServiceProvider() возвращает null

enter image description here

public class TextTemplatingEngineHost : ITextTemplatingEngineHost
{
    internal string TemplateFileValue;
    public string TemplateFile
    {
        get { return TemplateFileValue; }
    }
    public string FileExtension { get; private set; } = ".cs";
    public Encoding FileEncoding { get; private set; } = Encoding.UTF8;
    public CompilerErrorCollection Errors { get; private set; }

    public IList<string> StandardAssemblyReferences
    {
        get
        {
            return new string[]
            {
                typeof(System.Windows.Forms.AccessibleEvents).Assembly.Location
            };
        }
    }

    public IList<string> StandardImports
    {
        get
        {
            return new string[]
            {
                "System",
                "System.IO",
                "System.Diagnostics",
                "System.Linq",
                "System.Collections",
                "System.Collections.Generic"
            };
        }
    }

    public bool LoadIncludeText(string requestFileName, out string content, out string location)
    {
        content = string.Empty;
        location = 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;
        }

        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)
    {
        Errors = errors;
    }

    public AppDomain ProvideTemplatingAppDomain(string content)
    {
        return AppDomain.CreateDomain("Generation App Domain");
    }
}

В основной функции

var templateFileName = Path.Combine(Path.GetDirectoryName(Path.GetDirectoryName(Directory.GetCurrentDirectory())), "Template1.tt");

var host = new TextTemplatingEngineHost();
host.TemplateFileValue = templateFileName;

var template = new Template1();
template.Host = host;
var output = template.TransformText();

1 Ответ

0 голосов
/ 08 мая 2019

Вы можете легко записать вывод в определенные файлы и запретить шаблону записывать вывод в дочерний узел с несколькими строками кода.

Добавьте следующий код внизу шаблона или в конце итерации, если вы пишете несколько файлов.

<#
    SaveFile(entitiesFolder, entity.Name, this.GenerationEnvironment.ToString());
    this.GenerationEnvironment.Remove(0, this.GenerationEnvironment.Length); //Removes the output
#> 

Метод SaveFile - это просто streamWriter, который пишет в определенную папку или путь.

public void SaveFile(string folder, string fileName, string content)
{
    using (FileStream fs = new FileStream(Path.Combine(folder, fileName.Trim() + ".cs"), FileMode.Create))
    {
        using (StreamWriter str = new StreamWriter(fs))
        {
            str.WriteLine(content);
            str.Flush();
        }
    }
}

Я экспериментирую с этим здесь . Я также пробовал этот файл менеджера до этого.

...