T4报告编译转换:类,结构中的标记'this'无效

Mit*_*tch 16 t4 visual-studio-2013

试图为Immutable Object Graph运行T4模板会产生错误

??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
? 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 ?
??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)

报告的行始终是第1行,并且完整的t4模板集是数百行.如何解决并解决此问题?

Mit*_*tch 39

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

更改

<#@ template debug="true" language="C#" #>
<#+
// scriptlet
#>
                                              <-- empty line here
Run Code Online (Sandbox Code Playgroud)

<#@ template debug="true" language="C#" #>
<#+
// scriptlet
#>
Run Code Online (Sandbox Code Playgroud)

调试

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

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

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

检查从模板生成的变换器在该TransformText()方法之外显示如下行.看起来,在scriptlet(<#+ #>)之后的源模板中的任何文字都将被置于生成的生成器类中.

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

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

  • 我想这个信息对99%的读者来说最重要:"删除每个模板文件末尾的换行符解决了这个问题." (4认同)

Cam*_*ron 12

对我来说,文件末尾的尾部换行不是问题,但是使用Unix行结尾(\n)而不是Windows行结尾(\ r \n)打破了T4引擎.

当你有两个看起来相同的文件但其中一个文件无法编译时,调试非常令人沮丧!

  • 就我而言,这个答案解决了我的问题,本文解释了如何详细解决问题 - https://www.teamdevelopmentforsitecore.com/Blog/t4-transform-file-problems-code-gen 每当我们转换版本控制时在 GitHub 上,仍然会出现一些随机的 CR LF 问题,就像这个。 (2认同)