See https://msdn.microsoft.com/en-us/library/bb126579.aspx for more details
상속: ITextTemplatingEngineHost, IServiceProvider
        /// <summary>
        /// /
        /// </summary>
        /// <param name="dte"></param>
        /// <param name="templateFileName"></param>
        /// <param name="resolver"></param>
        /// <returns></returns>
        public static Tuple<string, VisualStudioTextTemplateHost> ProcessTemplateInMemory(DTE2 dte, string templateFileName, IVariableResolver resolver)
        {
            if (dte == null)
            {
                throw new ArgumentNullException("dte");
            }
            if (string.IsNullOrEmpty(templateFileName) || !File.Exists(templateFileName))
            {
                throw new ArgumentException(Resources.Program_ProcessTemplateInMemory_String_is_null_or_empty_or_file_doesn_t_exist_, templateFileName);
            }

            //// This would be WAY more elegant, but it spawns a confirmation box...
            ////printfn "Transforming templates..."
            ////dte.ExecuteCommand("TextTransformation.TransformAllTemplates")

            Source.TraceEvent(TraceEventType.Information, 0, Resources.Program_ProcessTemplate_Processing___0_____, templateFileName);

            var templateDir = Path.GetDirectoryName(templateFileName);
            Debug.Assert(templateDir != null, "templateDir != null, don't expect templateFileName to be a root directory.");
            //  Setup Environment
            var oldDir = Environment.CurrentDirectory;
            try
            {
                Environment.CurrentDirectory = templateDir;

                // Setup NamespaceHint in CallContext
                var templateFileItem = dte.Solution.FindProjectItem(templateFileName);
                var project = templateFileItem.ContainingProject;
                var projectDir = Path.GetDirectoryName(project.FullName);
                Debug.Assert(projectDir != null, "projectDir != null, don't expect project.FullName to be a root directory.");
                string defaultNamespace = project.Properties.Item("DefaultNamespace").Value.ToString();
                var templateFileNameUpper = templateFileName.ToUpperInvariant();
                var projectDirUpper = projectDir.ToUpperInvariant();
                Debug.Assert(templateFileNameUpper.StartsWith(projectDirUpper, StringComparison.Ordinal), "Template file-name is not within the project directory.");

                var finalNamespace = defaultNamespace;
                if (templateDir.Length != projectDir.Length)
                {
                    var relativeNamespace =
                        templateDir.Substring(projectDir.Length + 1)
                            // BUG? Handle all namespace relevant characters
                            .Replace("\\", ".").Replace("/", ".");
                    finalNamespace =
                        string.Format(CultureInfo.InvariantCulture, "{0}.{1}", defaultNamespace, relativeNamespace);
                }

                using (new LogicalCallContextChange("NamespaceHint", finalNamespace))
                {

                    var host = new VisualStudioTextTemplateHost(templateFileName, dte, resolver);
                    var engine = new Engine();
                    var input = File.ReadAllText(templateFileName);
                    var output = engine.ProcessTemplate(input, host);
                    return Tuple.Create(output, host);
                }
            }
            finally
            {
                Environment.CurrentDirectory = oldDir;
            }
        }
        /// <summary>
        /// /
        /// </summary>
        /// <param name="dte"></param>
        /// <param name="templateFileName"></param>
        /// <param name="resolver"></param>
        /// <returns></returns>
        public static Tuple <string, VisualStudioTextTemplateHost> ProcessTemplateInMemory(DTE2 dte, string templateFileName, IVariableResolver resolver)
        {
            if (dte == null)
            {
                throw new ArgumentNullException("dte");
            }
            if (string.IsNullOrEmpty(templateFileName) || !File.Exists(templateFileName))
            {
                throw new ArgumentException(Resources.Program_ProcessTemplateInMemory_String_is_null_or_empty_or_file_doesn_t_exist_, templateFileName);
            }

            //// This would be WAY more elegant, but it spawns a confirmation box...
            ////printfn "Transforming templates..."
            ////dte.ExecuteCommand("TextTransformation.TransformAllTemplates")

            Source.TraceEvent(TraceEventType.Information, 0, Resources.Program_ProcessTemplate_Processing___0_____, templateFileName);

            var templateDir = Path.GetDirectoryName(templateFileName);

            Debug.Assert(templateDir != null, "templateDir != null, don't expect templateFileName to be a root directory.");
            //  Setup Environment
            var oldDir = Environment.CurrentDirectory;

            try
            {
                Environment.CurrentDirectory = templateDir;

                // Setup NamespaceHint in CallContext
                var templateFileItem = dte.Solution.FindProjectItem(templateFileName);
                var project          = templateFileItem.ContainingProject;
                var projectDir       = Path.GetDirectoryName(project.FullName);
                Debug.Assert(projectDir != null, "projectDir != null, don't expect project.FullName to be a root directory.");
                string defaultNamespace      = project.Properties.Item("DefaultNamespace").Value.ToString();
                var    templateFileNameUpper = templateFileName.ToUpperInvariant();
                var    projectDirUpper       = projectDir.ToUpperInvariant();
                Debug.Assert(templateFileNameUpper.StartsWith(projectDirUpper, StringComparison.Ordinal), "Template file-name is not within the project directory.");

                var finalNamespace = defaultNamespace;
                if (templateDir.Length != projectDir.Length)
                {
                    var relativeNamespace =
                        templateDir.Substring(projectDir.Length + 1)
                        // BUG? Handle all namespace relevant characters
                        .Replace("\\", ".").Replace("/", ".");
                    finalNamespace =
                        string.Format(CultureInfo.InvariantCulture, "{0}.{1}", defaultNamespace, relativeNamespace);
                }

                using (new LogicalCallContextChange("NamespaceHint", finalNamespace))
                {
                    var host   = new VisualStudioTextTemplateHost(templateFileName, dte, resolver);
                    var engine = new Engine();
                    var input  = File.ReadAllText(templateFileName);
                    var output = engine.ProcessTemplate(input, host);
                    return(Tuple.Create(output, host));
                }
            }
            finally
            {
                Environment.CurrentDirectory = oldDir;
            }
        }