Free cookie consent management tool by TermsFeed Policy Generator

source: branches/OptimizationNetworks/HeuristicLab.Optimization.Networks/3.3/Core.Networks/ProgrammableNetworkItem.cs @ 11562

Last change on this file since 11562 was 11562, checked in by swagner, 9 years ago

#2205: Started working on programmable network items.

File size: 11.6 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 HeuristicLab.Common;
23using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
24using Microsoft.CSharp;
25using System;
26using System.CodeDom;
27using System.CodeDom.Compiler;
28using System.Collections.Generic;
29using System.Drawing;
30using System.IO;
31using System.Linq;
32using System.Reflection;
33using System.Text;
34
35namespace HeuristicLab.Core.Networks {
36  [Item("ProgrammableNetworkItem", "Abstract base class for programmable items of a network.")]
37  [StorableClass]
38  public abstract class ProgrammableNetworkItem : NetworkItem {
39    #region Item Properties
40    public static new Image StaticItemImage {
41      get { return HeuristicLab.Common.Resources.VSImageLibrary.Script; }
42    }
43    public override string ItemName {
44      get { return CompiledNetworkItem != null ? CompiledNetworkItem.ItemName : base.ItemName; }
45    }
46    public override string ItemDescription {
47      get { return CompiledNetworkItem != null ? CompiledNetworkItem.ItemDescription : base.ItemDescription; }
48    }
49    public override Image ItemImage {
50      get { return CompiledNetworkItem != null ? CompiledNetworkItem.ItemImage : base.ItemImage; }
51    }
52    #endregion
53
54    #region NamedItem Properties
55    public override bool CanChangeName {
56      get { return CompiledNetworkItem != null ? CompiledNetworkItem.CanChangeName : base.CanChangeName; }
57    }
58    public override bool CanChangeDescription {
59      get { return CompiledNetworkItem != null ? CompiledNetworkItem.CanChangeDescription : base.CanChangeDescription; }
60    }
61    #endregion
62
63    protected virtual string CodeTemplate {
64      get { return ReadCodeTemplate("ProgrammableNetworkItemTemplate.cs"); }
65    }
66
67    [Storable]
68    private string code;
69    public string Code {
70      get { return code; }
71      set {
72        if (value != code) {
73          code = value;
74          OnCodeChanged();
75        }
76      }
77    }
78
79    private CompilerErrorCollection compileErrors;
80    public CompilerErrorCollection CompileErrors {
81      get { return compileErrors; }
82      private set {
83        compileErrors = value;
84        OnCompileErrorsChanged();
85      }
86    }
87
88    private INetworkItem compiledNetworkItem;
89    protected INetworkItem CompiledNetworkItem {
90      get { return compiledNetworkItem; }
91      set {
92        if (compiledNetworkItem != value) {
93          if (compiledNetworkItem != null) DeregisterCompiledNetworkItemEvents();
94          compiledNetworkItem = value;
95          if (compiledNetworkItem != null) RegisterCompiledNetworkItemEvents();
96          OnCompiledNetworkItemChanged();
97          OnToStringChanged();
98          OnItemImageChanged();
99        }
100      }
101    }
102
103    [StorableConstructor]
104    protected ProgrammableNetworkItem(bool deserializing) : base(deserializing) { }
105    protected ProgrammableNetworkItem(ProgrammableNetworkItem original, Cloner cloner)
106      : base(original, cloner) {
107      code = original.code;
108      if (original.compileErrors != null)
109        compileErrors = new CompilerErrorCollection(original.compileErrors);
110      CompiledNetworkItem = cloner.Clone(original.compiledNetworkItem);
111    }
112    protected ProgrammableNetworkItem()
113      : base("ProgrammableNetworkItem") {
114      code = CodeTemplate;
115    }
116    protected ProgrammableNetworkItem(string name)
117      : base(name) {
118      code = CodeTemplate;
119    }
120    protected ProgrammableNetworkItem(string name, string description)
121      : base(name, description) {
122      code = CodeTemplate;
123    }
124
125    public override string ToString() {
126      return CompiledNetworkItem != null ? CompiledNetworkItem.ToString() : base.ToString();
127    }
128
129    #region Compilation
130    public virtual void Compile() {
131      var codeProvider = new CSharpCodeProvider(
132        new Dictionary<string, string> {
133          {"CompilerVersion", "v4.0"}, // support C# 4.0 syntax
134        }
135      );
136      var compilerParams = new CompilerParameters {
137        GenerateExecutable = false,
138        GenerateInMemory = true,
139        IncludeDebugInformation = true,
140        WarningLevel = 4
141      };
142      compilerParams.ReferencedAssemblies.AddRange(
143        GetAssemblies().Select(a => a.Location).ToArray()
144      );
145      var results = codeProvider.CompileAssemblyFromSource(compilerParams, code);
146      CompileErrors = results.Errors;
147      if (results.Errors.HasErrors) {
148        var sb = new StringBuilder();
149        foreach (CompilerError error in results.Errors) {
150          sb.Append(error.Line).Append(':')
151            .Append(error.Column).Append(": ")
152            .AppendLine(error.ErrorText);
153        }
154        throw new Exception(string.Format("Compilation of \"{0}\" failed:{1}{2}",
155          Name, Environment.NewLine, sb.ToString()));
156      }
157      var assembly = results.CompiledAssembly;
158      compiledNetworkItem = (INetworkItem)Activator.CreateInstance(assembly.GetTypes().Single(x => typeof(CompiledProgrammableNetworkItem).IsAssignableFrom(x)), this);
159    }
160    #endregion
161
162    public event EventHandler CodeChanged;
163    protected virtual void OnCodeChanged() {
164      var handler = CodeChanged;
165      if (handler != null) handler(this, EventArgs.Empty);
166    }
167    public event EventHandler CompileErrorsChanged;
168    protected virtual void OnCompileErrorsChanged() {
169      var handler = CompileErrorsChanged;
170      if (handler != null) handler(this, EventArgs.Empty);
171    }
172    public event EventHandler CompiledNetworkItemChanged;
173    protected virtual void OnCompiledNetworkItemChanged() {
174      var handler = CompiledNetworkItemChanged;
175      if (handler != null) handler(this, EventArgs.Empty);
176    }
177
178    #region CompiledNetworkItem Events
179    protected virtual void RegisterCompiledNetworkItemEvents() {
180      if (compiledNetworkItem != null) {
181        compiledNetworkItem.ToStringChanged += CompiledNetworkItem_ToStringChanged;
182        compiledNetworkItem.ItemImageChanged += CompiledNetworkItem_ItemImageChanged;
183      }
184    }
185    protected virtual void DeregisterCompiledNetworkItemEvents() {
186      if (compiledNetworkItem != null) {
187        compiledNetworkItem.ToStringChanged -= CompiledNetworkItem_ToStringChanged;
188        compiledNetworkItem.ItemImageChanged -= CompiledNetworkItem_ItemImageChanged;
189      }
190    }
191    private void CompiledNetworkItem_ToStringChanged(object sender, EventArgs e) {
192      OnToStringChanged();
193    }
194    private void CompiledNetworkItem_ItemImageChanged(object sender, EventArgs e) {
195      OnItemImageChanged();
196    }
197    #endregion
198
199    #region CompiledProgrammableNetworkItem
200    [Item("CompiledProgrammableNetworkItem", "Abstract base class for compiled programmable items of a network.")]
201    public abstract class CompiledProgrammableNetworkItem : Item, INetworkItem {
202      public static new Image StaticItemImage {
203        get { return HeuristicLab.Common.Resources.VSImageLibrary.Script; }
204      }
205
206      protected ProgrammableNetworkItem Context { get; private set; }
207
208      protected CompiledProgrammableNetworkItem(CompiledProgrammableNetworkItem original, Cloner cloner)
209        : base(original, cloner) {
210        Context = cloner.Clone(original.Context);
211        RegisterContextEvents();
212      }
213      protected CompiledProgrammableNetworkItem(ProgrammableNetworkItem context) {
214        Context = context;
215        RegisterContextEvents();
216      }
217
218      public override string ToString() {
219        return Name;
220      }
221
222      #region INamedItem Members
223      public string Name {
224        get { return Context.Name; }
225        set { Context.Name = value; }
226      }
227      public virtual bool CanChangeName {
228        get { return true; }
229      }
230      public string Description {
231        get { return Context.Description; }
232        set { Context.Description = value; }
233      }
234      public virtual bool CanChangeDescription {
235        get { return true; }
236      }
237
238      public event EventHandler<CancelEventArgs<string>> NameChanging;
239      protected virtual void OnNameChanging(CancelEventArgs<string> e) {
240        var handler = NameChanging;
241        if (handler != null) handler(this, e);
242      }
243      public event EventHandler NameChanged;
244      protected virtual void OnNameChanged() {
245        var handler = NameChanged;
246        if (handler != null) handler(this, EventArgs.Empty);
247        OnToStringChanged();
248      }
249      public event EventHandler DescriptionChanged;
250      protected virtual void OnDescriptionChanged() {
251        var handler = DescriptionChanged;
252        if (handler != null) handler(this, EventArgs.Empty);
253      }
254      #endregion
255
256      #region INetworkItem Members
257      public INetworkItem Parent {
258        get { return Context.Parent; }
259      }
260      public IEnumerable<INetworkItem> Children {
261        get { return Context.Children; }
262      }
263      #endregion
264
265      #region Context Events
266      protected virtual void RegisterContextEvents() {
267        Context.NameChanging += Context_NameChanging;
268        Context.NameChanged += Context_NameChanged;
269        Context.DescriptionChanged += Context_DescriptionChanged;
270        Context.CompiledNetworkItemChanged += Context_CompiledNetworkItemChanged;
271      }
272      protected virtual void DeregisterContextEvents() {
273        Context.NameChanging -= Context_NameChanging;
274        Context.NameChanged -= Context_NameChanged;
275        Context.DescriptionChanged -= Context_DescriptionChanged;
276        Context.CompiledNetworkItemChanged -= Context_CompiledNetworkItemChanged;
277      }
278      private void Context_NameChanging(object sender, CancelEventArgs<string> e) {
279        OnNameChanging(e);
280      }
281      private void Context_NameChanged(object sender, EventArgs e) {
282        OnNameChanged();
283      }
284      private void Context_DescriptionChanged(object sender, EventArgs e) {
285        OnDescriptionChanged();
286      }
287      private void Context_CompiledNetworkItemChanged(object sender, EventArgs e) {
288        DeregisterContextEvents();
289      }
290      #endregion
291    }
292    #endregion
293
294    #region Helpers
295    protected virtual IEnumerable<Assembly> GetAssemblies() {
296      foreach (var a in AppDomain.CurrentDomain.GetAssemblies()) {
297        bool valid = false;
298        try {
299          valid = File.Exists(a.Location);
300        }
301        catch (NotSupportedException) {
302          // NotSupportedException is thrown while accessing
303          // the Location property of the anonymously hosted
304          // dynamic methods assembly, which is related to
305          // LINQ queries
306        }
307        if (valid) yield return a;
308      }
309    }
310    protected string ReadCodeTemplate(string templateName) {
311      using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(templateName))
312      using (var reader = new StreamReader(stream)) {
313        return reader.ReadToEnd();
314      }
315    }
316    #endregion
317  }
318}
Note: See TracBrowser for help on using the repository browser.