Free cookie consent management tool by TermsFeed Policy Generator

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

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

#2205: Continued working on programmable network items

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