Index: branches/OptimizationNetworks/HeuristicLab.Optimization.Networks/3.3/Core.Networks/ProgrammableNetworkItem.cs
===================================================================
--- branches/OptimizationNetworks/HeuristicLab.Optimization.Networks/3.3/Core.Networks/ProgrammableNetworkItem.cs	(revision 11562)
+++ branches/OptimizationNetworks/HeuristicLab.Optimization.Networks/3.3/Core.Networks/ProgrammableNetworkItem.cs	(revision 11562)
@@ -0,0 +1,318 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2014 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using Microsoft.CSharp;
+using System;
+using System.CodeDom;
+using System.CodeDom.Compiler;
+using System.Collections.Generic;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+
+namespace HeuristicLab.Core.Networks {
+  [Item("ProgrammableNetworkItem", "Abstract base class for programmable items of a network.")]
+  [StorableClass]
+  public abstract class ProgrammableNetworkItem : NetworkItem {
+    #region Item Properties
+    public static new Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Script; }
+    }
+    public override string ItemName {
+      get { return CompiledNetworkItem != null ? CompiledNetworkItem.ItemName : base.ItemName; }
+    }
+    public override string ItemDescription {
+      get { return CompiledNetworkItem != null ? CompiledNetworkItem.ItemDescription : base.ItemDescription; }
+    }
+    public override Image ItemImage {
+      get { return CompiledNetworkItem != null ? CompiledNetworkItem.ItemImage : base.ItemImage; }
+    }
+    #endregion
+
+    #region NamedItem Properties
+    public override bool CanChangeName {
+      get { return CompiledNetworkItem != null ? CompiledNetworkItem.CanChangeName : base.CanChangeName; }
+    }
+    public override bool CanChangeDescription {
+      get { return CompiledNetworkItem != null ? CompiledNetworkItem.CanChangeDescription : base.CanChangeDescription; }
+    }
+    #endregion
+
+    protected virtual string CodeTemplate {
+      get { return ReadCodeTemplate("ProgrammableNetworkItemTemplate.cs"); }
+    }
+
+    [Storable]
+    private string code;
+    public string Code {
+      get { return code; }
+      set {
+        if (value != code) {
+          code = value;
+          OnCodeChanged();
+        }
+      }
+    }
+
+    private CompilerErrorCollection compileErrors;
+    public CompilerErrorCollection CompileErrors {
+      get { return compileErrors; }
+      private set {
+        compileErrors = value;
+        OnCompileErrorsChanged();
+      }
+    }
+
+    private INetworkItem compiledNetworkItem;
+    protected INetworkItem CompiledNetworkItem {
+      get { return compiledNetworkItem; }
+      set {
+        if (compiledNetworkItem != value) {
+          if (compiledNetworkItem != null) DeregisterCompiledNetworkItemEvents();
+          compiledNetworkItem = value;
+          if (compiledNetworkItem != null) RegisterCompiledNetworkItemEvents();
+          OnCompiledNetworkItemChanged();
+          OnToStringChanged();
+          OnItemImageChanged();
+        }
+      }
+    }
+
+    [StorableConstructor]
+    protected ProgrammableNetworkItem(bool deserializing) : base(deserializing) { }
+    protected ProgrammableNetworkItem(ProgrammableNetworkItem original, Cloner cloner)
+      : base(original, cloner) {
+      code = original.code;
+      if (original.compileErrors != null)
+        compileErrors = new CompilerErrorCollection(original.compileErrors);
+      CompiledNetworkItem = cloner.Clone(original.compiledNetworkItem);
+    }
+    protected ProgrammableNetworkItem()
+      : base("ProgrammableNetworkItem") {
+      code = CodeTemplate;
+    }
+    protected ProgrammableNetworkItem(string name)
+      : base(name) {
+      code = CodeTemplate;
+    }
+    protected ProgrammableNetworkItem(string name, string description)
+      : base(name, description) {
+      code = CodeTemplate;
+    }
+
+    public override string ToString() {
+      return CompiledNetworkItem != null ? CompiledNetworkItem.ToString() : base.ToString();
+    }
+
+    #region Compilation
+    public virtual void Compile() {
+      var codeProvider = new CSharpCodeProvider(
+        new Dictionary<string, string> {
+          {"CompilerVersion", "v4.0"}, // support C# 4.0 syntax
+        }
+      );
+      var compilerParams = new CompilerParameters {
+        GenerateExecutable = false,
+        GenerateInMemory = true,
+        IncludeDebugInformation = true,
+        WarningLevel = 4
+      };
+      compilerParams.ReferencedAssemblies.AddRange(
+        GetAssemblies().Select(a => a.Location).ToArray()
+      );
+      var results = codeProvider.CompileAssemblyFromSource(compilerParams, code);
+      CompileErrors = results.Errors;
+      if (results.Errors.HasErrors) {
+        var sb = new StringBuilder();
+        foreach (CompilerError error in results.Errors) {
+          sb.Append(error.Line).Append(':')
+            .Append(error.Column).Append(": ")
+            .AppendLine(error.ErrorText);
+        }
+        throw new Exception(string.Format("Compilation of \"{0}\" failed:{1}{2}",
+          Name, Environment.NewLine, sb.ToString()));
+      }
+      var assembly = results.CompiledAssembly;
+      compiledNetworkItem = (INetworkItem)Activator.CreateInstance(assembly.GetTypes().Single(x => typeof(CompiledProgrammableNetworkItem).IsAssignableFrom(x)), this);
+    }
+    #endregion
+
+    public event EventHandler CodeChanged;
+    protected virtual void OnCodeChanged() {
+      var handler = CodeChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler CompileErrorsChanged;
+    protected virtual void OnCompileErrorsChanged() {
+      var handler = CompileErrorsChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler CompiledNetworkItemChanged;
+    protected virtual void OnCompiledNetworkItemChanged() {
+      var handler = CompiledNetworkItemChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    #region CompiledNetworkItem Events
+    protected virtual void RegisterCompiledNetworkItemEvents() {
+      if (compiledNetworkItem != null) {
+        compiledNetworkItem.ToStringChanged += CompiledNetworkItem_ToStringChanged;
+        compiledNetworkItem.ItemImageChanged += CompiledNetworkItem_ItemImageChanged;
+      }
+    }
+    protected virtual void DeregisterCompiledNetworkItemEvents() {
+      if (compiledNetworkItem != null) {
+        compiledNetworkItem.ToStringChanged -= CompiledNetworkItem_ToStringChanged;
+        compiledNetworkItem.ItemImageChanged -= CompiledNetworkItem_ItemImageChanged;
+      }
+    }
+    private void CompiledNetworkItem_ToStringChanged(object sender, EventArgs e) {
+      OnToStringChanged();
+    }
+    private void CompiledNetworkItem_ItemImageChanged(object sender, EventArgs e) {
+      OnItemImageChanged();
+    }
+    #endregion
+
+    #region CompiledProgrammableNetworkItem
+    [Item("CompiledProgrammableNetworkItem", "Abstract base class for compiled programmable items of a network.")]
+    public abstract class CompiledProgrammableNetworkItem : Item, INetworkItem {
+      public static new Image StaticItemImage {
+        get { return HeuristicLab.Common.Resources.VSImageLibrary.Script; }
+      }
+
+      protected ProgrammableNetworkItem Context { get; private set; }
+
+      protected CompiledProgrammableNetworkItem(CompiledProgrammableNetworkItem original, Cloner cloner)
+        : base(original, cloner) {
+        Context = cloner.Clone(original.Context);
+        RegisterContextEvents();
+      }
+      protected CompiledProgrammableNetworkItem(ProgrammableNetworkItem context) {
+        Context = context;
+        RegisterContextEvents();
+      }
+
+      public override string ToString() {
+        return Name;
+      }
+
+      #region INamedItem Members
+      public string Name {
+        get { return Context.Name; }
+        set { Context.Name = value; }
+      }
+      public virtual bool CanChangeName {
+        get { return true; }
+      }
+      public string Description {
+        get { return Context.Description; }
+        set { Context.Description = value; }
+      }
+      public virtual bool CanChangeDescription {
+        get { return true; }
+      }
+
+      public event EventHandler<CancelEventArgs<string>> NameChanging;
+      protected virtual void OnNameChanging(CancelEventArgs<string> e) {
+        var handler = NameChanging;
+        if (handler != null) handler(this, e);
+      }
+      public event EventHandler NameChanged;
+      protected virtual void OnNameChanged() {
+        var handler = NameChanged;
+        if (handler != null) handler(this, EventArgs.Empty);
+        OnToStringChanged();
+      }
+      public event EventHandler DescriptionChanged;
+      protected virtual void OnDescriptionChanged() {
+        var handler = DescriptionChanged;
+        if (handler != null) handler(this, EventArgs.Empty);
+      }
+      #endregion
+
+      #region INetworkItem Members
+      public INetworkItem Parent {
+        get { return Context.Parent; }
+      }
+      public IEnumerable<INetworkItem> Children {
+        get { return Context.Children; }
+      }
+      #endregion
+
+      #region Context Events
+      protected virtual void RegisterContextEvents() {
+        Context.NameChanging += Context_NameChanging;
+        Context.NameChanged += Context_NameChanged;
+        Context.DescriptionChanged += Context_DescriptionChanged;
+        Context.CompiledNetworkItemChanged += Context_CompiledNetworkItemChanged;
+      }
+      protected virtual void DeregisterContextEvents() {
+        Context.NameChanging -= Context_NameChanging;
+        Context.NameChanged -= Context_NameChanged;
+        Context.DescriptionChanged -= Context_DescriptionChanged;
+        Context.CompiledNetworkItemChanged -= Context_CompiledNetworkItemChanged;
+      }
+      private void Context_NameChanging(object sender, CancelEventArgs<string> e) {
+        OnNameChanging(e);
+      }
+      private void Context_NameChanged(object sender, EventArgs e) {
+        OnNameChanged();
+      }
+      private void Context_DescriptionChanged(object sender, EventArgs e) {
+        OnDescriptionChanged();
+      }
+      private void Context_CompiledNetworkItemChanged(object sender, EventArgs e) {
+        DeregisterContextEvents();
+      }
+      #endregion
+    }
+    #endregion
+
+    #region Helpers
+    protected virtual IEnumerable<Assembly> GetAssemblies() {
+      foreach (var a in AppDomain.CurrentDomain.GetAssemblies()) {
+        bool valid = false;
+        try {
+          valid = File.Exists(a.Location);
+        }
+        catch (NotSupportedException) {
+          // NotSupportedException is thrown while accessing 
+          // the Location property of the anonymously hosted
+          // dynamic methods assembly, which is related to
+          // LINQ queries
+        }
+        if (valid) yield return a;
+      }
+    }
+    protected string ReadCodeTemplate(string templateName) {
+      using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(templateName))
+      using (var reader = new StreamReader(stream)) {
+        return reader.ReadToEnd();
+      }
+    }
+    #endregion
+  }
+}
Index: branches/OptimizationNetworks/HeuristicLab.Optimization.Networks/3.3/Core.Networks/ProgrammableNetworkItemTemplate.cs
===================================================================
--- branches/OptimizationNetworks/HeuristicLab.Optimization.Networks/3.3/Core.Networks/ProgrammableNetworkItemTemplate.cs	(revision 11562)
+++ branches/OptimizationNetworks/HeuristicLab.Optimization.Networks/3.3/Core.Networks/ProgrammableNetworkItemTemplate.cs	(revision 11562)
@@ -0,0 +1,35 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2014 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using System;
+
+namespace HeuristicLab.Core.Networks {
+  [Item("MyProgrammableNetworkItem", "A programmable item of a network.")]
+  public class MyProgrammableNetworkItem : ProgrammableNetworkItem.CompiledProgrammableNetworkItem {
+    protected MyProgrammableNetworkItem(MyProgrammableNetworkItem original, Cloner cloner) : base(original, cloner) { }
+    protected MyProgrammableNetworkItem(ProgrammableNetworkItem context) : base(context) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MyProgrammableNetworkItem(this, cloner);
+    }
+  }
+}
Index: branches/OptimizationNetworks/HeuristicLab.Optimization.Networks/3.3/Core.Networks/ProgrammableNode.cs
===================================================================
--- branches/OptimizationNetworks/HeuristicLab.Optimization.Networks/3.3/Core.Networks/ProgrammableNode.cs	(revision 11562)
+++ branches/OptimizationNetworks/HeuristicLab.Optimization.Networks/3.3/Core.Networks/ProgrammableNode.cs	(revision 11562)
@@ -0,0 +1,211 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2014 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+
+namespace HeuristicLab.Core.Networks {
+  [Item("ProgrammableNode", "A programmable node of a network.")]
+  [StorableClass]
+  public class ProgrammableNode : ProgrammableNetworkItem, INode {
+    protected override string CodeTemplate {
+      get { return ReadCodeTemplate("ProgrammableNodeTemplate.cs"); }
+    }
+
+    new public INetwork Parent {
+      get { return (INetwork)base.Parent; }
+      set {
+        // NOTE: never call setter directly as the Parent property is set by the network which contains the node
+        base.Parent = value;
+      }
+    }
+    public override IEnumerable<INetworkItem> Children {
+      get { return base.Children.Concat(Ports.AsEnumerable<INetworkItem>()); }
+    }
+
+    [Storable]
+    private PortCollection ports;
+    protected PortCollection Ports {
+      get { return ports; }
+    }
+    private ReadOnlyKeyedItemCollection<string, IPort> readOnlyPorts;
+    IKeyedItemCollection<string, IPort> INode.Ports {
+      get {
+        if (readOnlyPorts == null) readOnlyPorts = ports.AsReadOnly();
+        return readOnlyPorts;
+      }
+    }
+
+    [StorableConstructor]
+    private ProgrammableNode(bool deserializing) : base(deserializing) { }
+    private ProgrammableNode(ProgrammableNode original, Cloner cloner)
+      : base(original, cloner) {
+      ports = cloner.Clone(original.ports);
+      foreach (var p in Ports)
+        p.Parent = this;
+      readOnlyPorts = null;
+      RegisterPortsEvents();
+    }
+    public ProgrammableNode()
+      : base("ProgrammableNode") {
+      ports = new PortCollection();
+      readOnlyPorts = null;
+      RegisterPortsEvents();
+    }
+    public ProgrammableNode(string name)
+      : base(name) {
+      ports = new PortCollection();
+      readOnlyPorts = null;
+      RegisterPortsEvents();
+    }
+    public ProgrammableNode(string name, string description)
+      : base(name, description) {
+      ports = new PortCollection();
+      readOnlyPorts = null;
+      RegisterPortsEvents();
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      foreach (var p in Ports)
+        p.Parent = this;
+      RegisterPortsEvents();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ProgrammableNode(this, cloner);
+    }
+
+    #region Ports Events
+    protected virtual void RegisterPortsEvents() {
+      ports.ItemsAdded += Ports_ItemsAdded;
+      ports.ItemsRemoved += Ports_ItemsRemoved;
+      ports.ItemsReplaced += Ports_ItemsReplaced;
+      ports.CollectionReset += Ports_CollectionReset;
+    }
+    protected virtual void Ports_ItemsAdded(object sender, Collections.CollectionItemsChangedEventArgs<IPort> e) {
+      foreach (var p in e.Items)
+        p.Parent = this;
+    }
+    protected virtual void Ports_ItemsRemoved(object sender, Collections.CollectionItemsChangedEventArgs<IPort> e) {
+      foreach (var p in e.Items)
+        p.Parent = null;
+    }
+    protected virtual void Ports_ItemsReplaced(object sender, Collections.CollectionItemsChangedEventArgs<IPort> e) {
+      foreach (var p in e.OldItems)
+        p.Parent = null;
+      foreach (var p in e.Items)
+        p.Parent = this;
+    }
+    protected virtual void Ports_CollectionReset(object sender, Collections.CollectionItemsChangedEventArgs<IPort> e) {
+      foreach (var p in e.OldItems)
+        p.Parent = null;
+      foreach (var p in e.Items)
+        p.Parent = this;
+    }
+    #endregion
+
+    #region CompiledProgrammableNode
+    [Item("CompiledProgrammableNode", "Abstract base class for compiled programmable nodes of a network.")]
+    public abstract class CompiledProgrammableNode : CompiledProgrammableNetworkItem, INode {
+      protected new ProgrammableNode Context {
+        get { return (ProgrammableNode)base.Context; }
+      }
+
+      protected CompiledProgrammableNode(CompiledProgrammableNode original, Cloner cloner)
+        : base(original, cloner) {
+      }
+      protected CompiledProgrammableNode(ProgrammableNode context)
+        : base(context) {
+      }
+
+      #region INode Members
+      public new INetwork Parent {
+        get { return Context.Parent; }
+        set {
+          // NOTE: never call setter directly as the Parent property is set by the network which contains the node
+          Context.Parent = value;
+        }
+      }
+
+      public IKeyedItemCollection<string, IPort> Ports {
+        get { return Context.Ports; }
+      }
+      #endregion
+
+      #region Context Events
+      protected override void RegisterContextEvents() {
+        base.RegisterContextEvents();
+        Context.Ports.ItemsAdded += Ports_ItemsAdded;
+        Context.Ports.ItemsRemoved += Ports_ItemsRemoved;
+        Context.Ports.ItemsReplaced += Ports_ItemsReplaced;
+        Context.Ports.CollectionReset += Ports_CollectionReset;
+        foreach (var p in Context.Ports)
+          RegisterPortEvents(p);
+      }
+      protected override void DeregisterContextEvents() {
+        foreach (var p in Context.Ports)
+          DeregisterPortEvents(p);
+        Context.Ports.ItemsAdded -= Ports_ItemsAdded;
+        Context.Ports.ItemsRemoved -= Ports_ItemsRemoved;
+        Context.Ports.ItemsReplaced -= Ports_ItemsReplaced;
+        Context.Ports.CollectionReset -= Ports_CollectionReset;
+        base.DeregisterContextEvents();
+      }
+      private void Ports_ItemsAdded(object sender, Collections.CollectionItemsChangedEventArgs<IPort> e) {
+        foreach (var p in e.Items)
+          RegisterPortEvents(p);
+      }
+      private void Ports_ItemsRemoved(object sender, Collections.CollectionItemsChangedEventArgs<IPort> e) {
+        foreach (var p in e.Items)
+          DeregisterPortEvents(p);
+      }
+      private void Ports_ItemsReplaced(object sender, Collections.CollectionItemsChangedEventArgs<IPort> e) {
+        foreach (var p in e.OldItems)
+          DeregisterPortEvents(p);
+        foreach (var p in e.Items)
+          RegisterPortEvents(p);
+      }
+      private void Ports_CollectionReset(object sender, Collections.CollectionItemsChangedEventArgs<IPort> e) {
+        foreach (var p in e.OldItems)
+          DeregisterPortEvents(p);
+        foreach (var p in e.Items)
+          RegisterPortEvents(p);
+      }
+      protected virtual void RegisterPortEvents(IPort port) {
+        var mp = port as IMessagePort;
+        if (mp != null)
+          mp.MessageReceived += MessagePort_MessageReceived;
+      }
+      protected virtual void DeregisterPortEvents(IPort port) {
+        var mp = port as IMessagePort;
+        if (mp != null)
+          mp.MessageReceived -= MessagePort_MessageReceived;
+      }
+      protected virtual void MessagePort_MessageReceived(object sender, EventArgs<IMessage, CancellationToken> e) { }
+      #endregion
+    }
+    #endregion
+  }
+}
Index: branches/OptimizationNetworks/HeuristicLab.Optimization.Networks/3.3/Core.Networks/ProgrammableNodeTemplate.cs
===================================================================
--- branches/OptimizationNetworks/HeuristicLab.Optimization.Networks/3.3/Core.Networks/ProgrammableNodeTemplate.cs	(revision 11562)
+++ branches/OptimizationNetworks/HeuristicLab.Optimization.Networks/3.3/Core.Networks/ProgrammableNodeTemplate.cs	(revision 11562)
@@ -0,0 +1,40 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2014 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using System;
+using System.Threading;
+
+namespace HeuristicLab.Core.Networks {
+  [Item("MyProgrammableNode", "A programmable node of a network.")]
+  public class MyProgrammableNode : ProgrammableNode.CompiledProgrammableNode {
+    protected MyProgrammableNode(MyProgrammableNode original, Cloner cloner) : base(original, cloner) { }
+    protected MyProgrammableNode(ProgrammableNode context) : base(context) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MyProgrammableNode(this, cloner);
+    }
+
+    protected override void MessagePort_MessageReceived(object sender, EventArgs<IMessage, CancellationToken> e) {
+      // implement processing of messages here
+    }
+  }
+}
Index: branches/OptimizationNetworks/HeuristicLab.Optimization.Networks/3.3/HeuristicLab.Optimization.Networks-3.3.csproj
===================================================================
--- branches/OptimizationNetworks/HeuristicLab.Optimization.Networks/3.3/HeuristicLab.Optimization.Networks-3.3.csproj	(revision 11561)
+++ branches/OptimizationNetworks/HeuristicLab.Optimization.Networks/3.3/HeuristicLab.Optimization.Networks-3.3.csproj	(revision 11562)
@@ -96,4 +96,7 @@
     <Compile Include="Core.Networks\IUserDefinedNode.cs" />
     <Compile Include="Core.Networks\MessagePort.cs" />
+    <EmbeddedResource Include="Core.Networks\ProgrammableNetworkItemTemplate.cs" />
+    <Compile Include="Core.Networks\ProgrammableNetworkItem.cs" />
+    <EmbeddedResource Include="Core.Networks\ProgrammableNodeTemplate.cs" />
     <Compile Include="Core.Networks\UserDefinedNetwork.cs" />
     <Compile Include="Core.Networks\IMessage.cs" />
@@ -120,4 +123,5 @@
     <Compile Include="Core.Networks\PortParameterType.cs" />
     <Compile Include="Core.Networks\UserDefinedMessagePort.cs" />
+    <Compile Include="Core.Networks\ProgrammableNode.cs" />
     <Compile Include="Core.Networks\UserDefinedNode.cs" />
     <Compile Include="Operators\HookOperator.cs" />
