source: trunk/sources/HeuristicLab.Scripting/3.3/Script.cs @ 11787

Last change on this file since 11787 was 11787, checked in by jkarder, 5 years ago

#2262: refactored code template loading

File size: 4.9 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2014 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.CodeDom;
24using System.CodeDom.Compiler;
25using System.Collections.Generic;
26using System.Drawing;
27using System.IO;
28using System.Linq;
29using System.Reflection;
30using System.Text;
31using HeuristicLab.Common;
32using HeuristicLab.Common.Resources;
33using HeuristicLab.Core;
34using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
35using Microsoft.CSharp;
36
37namespace HeuristicLab.Scripting {
38  [StorableClass]
39  public class Script : NamedItem {
40    protected virtual string CodeTemplate {
41      get { return string.Empty; }
42    }
43
44    #region Fields & Properties
45    public static new Image StaticItemImage {
46      get { return VSImageLibrary.Script; }
47    }
48
49    [Storable]
50    private string code;
51    public string Code {
52      get { return code; }
53      set {
54        if (value == code) return;
55        code = value;
56        OnCodeChanged();
57      }
58    }
59
60    private CompilerErrorCollection compileErrors;
61    public CompilerErrorCollection CompileErrors {
62      get { return compileErrors; }
63      private set {
64        compileErrors = value;
65        OnCompileErrorsChanged();
66      }
67    }
68    #endregion
69
70    #region Construction & Initialization
71    [StorableConstructor]
72    protected Script(bool deserializing) : base(deserializing) { }
73    protected Script(Script original, Cloner cloner)
74      : base(original, cloner) {
75      code = original.code;
76      if (original.compileErrors != null)
77        compileErrors = new CompilerErrorCollection(original.compileErrors);
78    }
79    public Script()
80      : base("Script", "An empty script.") {
81      code = CodeTemplate;
82    }
83    public Script(string code)
84      : this() {
85      this.code = code;
86    }
87
88    public override IDeepCloneable Clone(Cloner cloner) {
89      return new Script(this, cloner);
90    }
91    #endregion
92
93    #region Compilation
94    protected virtual CSharpCodeProvider CodeProvider {
95      get {
96        return new CSharpCodeProvider(
97          new Dictionary<string, string> {
98                {"CompilerVersion", "v4.0"}, // support C# 4.0 syntax
99              });
100      }
101    }
102
103    protected virtual CompilerResults DoCompile() {
104      var parameters = new CompilerParameters {
105        GenerateExecutable = false,
106        GenerateInMemory = true,
107        IncludeDebugInformation = true,
108        WarningLevel = 4
109      };
110
111      parameters.ReferencedAssemblies.AddRange(
112        GetAssemblies()
113        .Select(a => a.Location)
114        .ToArray());
115
116      return CodeProvider.CompileAssemblyFromSource(parameters, code);
117    }
118
119    public virtual Assembly Compile() {
120      var results = DoCompile();
121      CompileErrors = results.Errors;
122      if (results.Errors.HasErrors) {
123        var sb = new StringBuilder();
124        foreach (CompilerError error in results.Errors) {
125          sb.Append(error.Line).Append(':')
126            .Append(error.Column).Append(": ")
127            .AppendLine(error.ErrorText);
128        }
129        throw new InvalidOperationException(string.Format("Compilation of \"{0}\" failed:{1}{2}",
130          Name, Environment.NewLine, sb.ToString()));
131      } else {
132        return results.CompiledAssembly;
133      }
134    }
135
136    public virtual IEnumerable<Assembly> GetAssemblies() {
137      var assemblies = AppDomain.CurrentDomain.GetAssemblies().Where(a => !a.IsDynamic && File.Exists(a.Location)).ToList();
138      assemblies.Add(typeof(Microsoft.CSharp.RuntimeBinder.Binder).Assembly); // for dlr functionality
139      return assemblies;
140    }
141
142    protected virtual CodeCompileUnit CreateCompilationUnit() {
143      var unit = new CodeSnippetCompileUnit(code);
144      return unit;
145    }
146    #endregion
147
148    public event EventHandler CodeChanged;
149    protected virtual void OnCodeChanged() {
150      var handler = CodeChanged;
151      if (handler != null) handler(this, EventArgs.Empty);
152    }
153
154    public event EventHandler CompileErrorsChanged;
155    protected virtual void OnCompileErrorsChanged() {
156      var handler = CompileErrorsChanged;
157      if (handler != null) handler(this, EventArgs.Empty);
158    }
159  }
160}
Note: See TracBrowser for help on using the repository browser.