/// <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; }
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; }