T4 报告编译转换:类、结构中的无效标记“this" [英] T4 reports Compiling transformation: Invalid token 'this' in class, struct

查看:35
本文介绍了T4 报告编译转换:类、结构中的无效标记“this"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尝试运行 不可变对象图 的 T4 模板会出现

Attempting to run the T4 templates for Immutable Object Graph gives errors of

╔═══════╦═══╦══════════════════════════════════════════════════════════════════════════════════════════════════╦═════════════════════════════════════════════════════════╦═══╦════╦══════╗
║ Error ║ 5 ║ Compiling transformation: Invalid token 'this' in class, struct, or interface member declaration ║ c:\dev\ImmutableObjectGraph-master\2013\Demo\Message.tt ║ 1 ║  1 ║ Demo ║
║ Error ║ 6 ║ Compiling transformation: Method must have a return type                                         ║ c:\dev\ImmutableObjectGraph-master\2013\Demo\Message.tt ║ 1 ║  6 ║ Demo ║
║ Error ║ 7 ║ Compiling transformation: Type expected                                                          ║ c:\dev\ImmutableObjectGraph-master\2013\Demo\Message.tt ║ 1 ║ 12 ║ Demo ║
╚═══════╩═══╩══════════════════════════════════════════════════════════════════════════════════════════════════╩═════════════════════════════════════════════════════════╩═══╩════╩══════╝

报告的行总是第 1 行,全套 t4 模板有数百行.如何排查和解决此问题?

The line reported is always line 1, and the full set of t4 templates is many hundreds of lines. How do I troubleshoot and fix this issue?

推荐答案

在 T4 模板中不能在 scriptlet 之后使用文字.

You cannot have literals in a T4 template after a scriptlet.

改变

<#@ template debug="true" language="C#" #>
<#+
// scriptlet
#>
                                              <-- empty line here

<#@ template debug="true" language="C#" #>
<#+
// scriptlet
#>

调试

您可以通过调用查看T4引擎生成的C#PreProcessTemplate 带有自定义模板主机.

Debugging

You can see the C# being generated by the T4 engine by calling PreProcessTemplate with a custom templating host.

我为此修改了自定义模板主机示例:

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

namespace CustomHost
{
    class CustomCmdLineHost : ITextTemplatingEngineHost
    {
        public string TemplateFile { get; private set; }
        public string FileExtension { get; private set; }
        public Encoding FileEncoding { get; private set; }
        public CompilerErrorCollection Errors { get; private set; }

        public IList<string> StandardAssemblyReferences { get { return new[] { typeof(System.Uri).Assembly.Location }; } }
        public IList<string> StandardImports { get { return new string[] { "System" }; } }

        public CustomCmdLineHost(string file)
        {
            this.TemplateFile = file;
            this.FileEncoding = Encoding.UTF8;
            this.FileExtension = ".txt";
        }

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

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

            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)
        {
            return ResolvePath(assemblyReference);
        }

        public Type ResolveDirectiveProcessor(string processorName)
        {
            throw new Exception("Directive Processor not found");
        }

        public string ResolvePath(string fileName)
        {
            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)
        {
            return String.Empty;
        }

        public void SetFileExtension(string extension)
        {
            FileExtension = extension;
        }

        public void SetOutputEncoding(System.Text.Encoding encoding, bool fromOutputDirective)
        {
            FileEncoding = encoding;
        }

        public void LogErrors(CompilerErrorCollection errors)
        {
            Errors = errors;
        }

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

    class Program
    {
        static void Main(string[] args)
        {
            var templateFileName = args[0];

            CustomCmdLineHost host = new CustomCmdLineHost(templateFileName);
            Engine engine = new Engine();

            string language;
            string[] refs;
            var output = engine.PreprocessTemplate(
                // input file
                File.ReadAllText(templateFileName), host,
                "testClass", "testNamespace", out language, out refs);

            string outputFileName = Path.Combine(
                Path.GetDirectoryName(templateFileName),
                templateFileName + ".generator.cs");

            File.WriteAllText(outputFileName, output, host.FileEncoding);

            foreach (CompilerError error in host.Errors)
                Console.WriteLine(error.ToString());

            Console.ReadLine();
        }
    }
}

检查从模板生成的转换器在 TransformText() 方法之外显示如下所示的行.看起来,源模板中出现在 scriptlet (<#+ #>) 将被固定到生成的生成器类中.

Examining the transformer generated from the template showed lines like the following outside the TransformText() method. Seemingly, any literals in the source templates which came after a scriptlet (<#+ #>) would be placed in-fix into the generated generator class.

        #line 1 "C:\dev\ImmutableObjectGraph-master\2013\Demo\Fruit.tt"
this.Write("\n");

删除每个模板文件末尾的换行符解决了这个问题.

Removing the newline characters at the end of each template file resolved the issue.

这篇关于T4 报告编译转换:类、结构中的无效标记“this"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆