/// <summary>Compiles an assembly that contains one class per each distinct expression found in given template.</summary>
 public static TemplateExpressionFactory CompileExpressions(Template template)
 {
     TemplateCompilation compilation = GenerateAssemblySourceCode(template);
     Assembly asm = CompileAssembly(template, compilation);
     TemplateExpressionFactory compiledExpressionFactory = new TemplateExpressionFactory(asm);
     return compiledExpressionFactory;
 }
        private static Assembly CompileAssembly(Template template, TemplateCompilation compilation)
        {
            string source = compilation.SourceCode;
            Assembly cachedAssembly = TemplateExpressionAssemblyCache.GetAssembly(source);
            if (cachedAssembly != null)
                return cachedAssembly;

            CompilerParameters config = new CompilerParameters() { GenerateInMemory = true };
            foreach (string asmName in template.ReferencedAssemblies)
                config.ReferencedAssemblies.Add(asmName);

            if (!config.ReferencedAssemblies.Contains("FistCore.Generator.TemplateEngine.dll"))
                config.ReferencedAssemblies.Add("FistCore.Generator.TemplateEngine.dll");

            if (!config.ReferencedAssemblies.Contains("FistCore.Core.dll"))
                config.ReferencedAssemblies.Add("FistCore.Core.dll");

            Dictionary<string, string> options = new Dictionary<string, string>();
            options["CompilerVersion"] = "v3.5";
            Microsoft.CSharp.CSharpCodeProvider compiler = new Microsoft.CSharp.CSharpCodeProvider(options);
            //CodeDomProvider compiler = CodeDomProvider.CreateProvider("CSharp");
            // All referenced assemblies must be in the same directory as entry assembly.
            string oldCwd = Directory.GetCurrentDirectory();
            Directory.SetCurrentDirectory(IoUtil.GetExecutableDirectory());
            CompilerResults output = compiler.CompileAssemblyFromSource(config, source);
            Directory.SetCurrentDirectory(oldCwd);
            if (output.Errors.HasErrors)
            {
                SetCompilerErrors(compilation, output.Errors);
                string errmsg = compilation.GetCompilationErrorsDescription();
                throw new Exception(template.Header.Title + Environment.NewLine + errmsg);
            }

            TemplateExpressionAssemblyCache.SetAssembly(source, output.CompiledAssembly);
            return output.CompiledAssembly;
        }
        private static void GenerateUsingDirectives(Template template, StringBuilder asmSource)
        {
            bool usesSystem = ArrayUtil.Exists<string>(template.Namespaces, (ns) => (ns == "System"));
            if (!usesSystem)
                asmSource.AppendLine("using System;");

            foreach (string name in template.Namespaces)
            {
                asmSource.AppendFormat("using {0};", name);
                asmSource.AppendLine();
            }

            if (template.Namespaces.Length > 0)
                asmSource.AppendLine();
        }
        private static TemplateCompilation GenerateAssemblySourceCode(Template template)
        {
            // One class (ITemplateExpression implementation) per expression.
            List<string> allDistinctExpressions = GetAllDistinctExpressions(template);
            TemplateCompilation compilation = new TemplateCompilation();
            StringBuilder asmSource = new StringBuilder();

            GenerateUsingDirectives(template, asmSource);
            asmSource.AppendLine(NamespaceDeclaration);
            asmSource.AppendLine(" {");

            List<string> generatedClassNames = new List<string>();
            int firstLineOfCurrClass = TextUtil.CountLines(asmSource.ToString()) + 1;
            foreach (string expression in allDistinctExpressions)
            {
                string className = CreateUniqueClassName(expression);
                if (!generatedClassNames.Contains(className))
                {
                    string classSourceCode = GenerateExpressionClassSource(className, expression);
                    asmSource.AppendLine(classSourceCode);

                    int currClassLineCount = TextUtil.CountLines(classSourceCode);
                    ExpressionCompilationItem compilationItem = new ExpressionCompilationItem()
                    {
                        ClassFirstLineInSourceFile = firstLineOfCurrClass,
                        ClassLastLineInSourceFile = firstLineOfCurrClass + currClassLineCount,
                        //ClassName = className,
                        //ClassSourceCode = classSourceCode,
                        Expression = expression,
                        XmlLine = template.XmlLines.GetLineWithText(expression)
                    };
                    compilation.Expressions.Add(compilationItem);

                    // 1st line of next class.
                    firstLineOfCurrClass = compilationItem.ClassLastLineInSourceFile + 1;
                }
            }

            asmSource.AppendLine(" }");
            compilation.SourceCode = asmSource.ToString();
            return compilation;
        }
        private static List<string> GetAllDistinctExpressions(Template template)
        {
            List<string> allDistinctExpressions = new List<string>();
            foreach (TemplateSegment segment in template.Segments)
            {
                var nonDistinctExpressions = GetAllExpressionsFromSegmentBody(segment.Body);
                foreach (string expression in nonDistinctExpressions)
                {
                    bool isNewExpression = !allDistinctExpressions.Contains(expression);
                    if (isNewExpression)
                        allDistinctExpressions.Add(expression);
                }
            }

            return allDistinctExpressions;
        }
Beispiel #6
0
 private void TryLoadSelectedTemplate()
 {
     if (File.Exists(this.uiTemplatePath.Text))
     {
         Template template = new Template();
         template.ReadXml(this.uiTemplatePath.Text);
         SetNewTemplateIfChanged(template);
     }
 }
        /// <summary>Initializes expression. This method can only be called once.</summary>
        /// <param name="template">Template to which the current expression belongs to. This expression implementation only supports <see cref="Template"/> class.</param>
        /// <param name="input">Input component.</param>
        void ITemplateExpression.Initialize(ITemplate template, ITemplateInputComponent input)
        {
            if (this.isInitialized)
                throw new InvalidOperationException("The expression is already initialized.");

            this.template = (Template)template;
            this.Variables = new TemplateVariableCollection(template.Variables);
            this.Input = input;
            this.isInitialized = true;
        }