Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/ApplicationBase.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/ApplicationBase.cs	(revision 16993)
+++ branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/ApplicationBase.cs	(revision 17013)
@@ -21,5 +21,5 @@
 
 
-using System;
+using HEAL.Attic;
 
 namespace HeuristicLab.PluginInfrastructure {
@@ -27,5 +27,5 @@
   /// Abstract base implementation for the IApplication interface.
   /// </summary>
-  [Serializable]
+  [StorableType("FB13839C-2EEC-4C6F-BEF3-A1CAE4467362")]
   public abstract class ApplicationBase : IApplication {
     /// <summary>
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/HeuristicLab.PluginInfrastructure-3.3.csproj
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/HeuristicLab.PluginInfrastructure-3.3.csproj	(revision 16993)
+++ branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/HeuristicLab.PluginInfrastructure-3.3.csproj	(revision 17013)
@@ -17,10 +17,11 @@
   </PropertyGroup>
   <ItemGroup>
-    <PackageReference Include="System.CodeDom" Version="4.5.0" />
-    <PackageReference Include="System.Drawing.Common" Version="4.5.1" />
     <PackageReference Include="System.Runtime.Loader" Version="4.3.0" />
-    <PackageReference Include="System.Security.Cryptography.ProtectedData" Version="4.5.0" />
-    <PackageReference Include="System.Configuration.ConfigurationManager" Version="4.5.0" />
-    <PackageReference Include="System.Security.Cryptography.Primitives" Version="4.3.0" />
+  </ItemGroup>
+  <ItemGroup>
+    <Reference Include="HEAL.Attic">
+      <HintPath>..\..\bin\HEAL.Attic.dll</HintPath>
+      <Private>true</Private>
+    </Reference>
   </ItemGroup>
 </Project>
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Interfaces/IRunner.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Interfaces/IRunner.cs	(revision 16993)
+++ branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Interfaces/IRunner.cs	(revision 17013)
@@ -3,9 +3,4 @@
 namespace HeuristicLab.PluginInfrastructure {
   public interface IRunner {
-    /// <summary>
-    /// Set this to true, if console output should be disabled.
-    /// </summary>
-    bool QuietMode { get; set; }
-
     /// <summary>
     /// Assemblies which the child process needs to load.
@@ -17,4 +12,8 @@
     /// </summary>
     void Run();
+
+    void Pause();
+    void Resume();
+    void Cancel();
   }
 }
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Interfaces/IRunnerHost.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Interfaces/IRunnerHost.cs	(revision 16993)
+++ branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Interfaces/IRunnerHost.cs	(revision 17013)
@@ -12,4 +12,9 @@
     /// </summary>
     RunnerState State { get; }
+
+    /// <summary>
+    /// Set this to true, if console output should be disabled.
+    /// </summary>
+    bool QuietMode { get; set; }
 
     /// <summary>
@@ -28,12 +33,8 @@
 
     /// <summary>
-    /// Method to pause the runner and the isolated IApplication.
+    /// Method to send messages to the runner, which runs in child process.
     /// </summary>
-    void Pause();
-
-    /// <summary>
-    /// Method to resume a paused runner and the isolated IApplication.
-    /// </summary>
-    void Resume();
+    /// <param name="runnerMessage">A object from a derived class of RunnerMessage.</param>
+    void Send(RunnerMessage runnerMessage);
   }
 }
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/ApplicationRunner.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/ApplicationRunner.cs	(revision 16993)
+++ branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/ApplicationRunner.cs	(revision 17013)
@@ -1,11 +1,11 @@
-﻿using System;
-using System.IO;
+﻿using HEAL.Attic;
 
 namespace HeuristicLab.PluginInfrastructure {
-  [Serializable]
+  [StorableType("612F98AF-E254-4C5E-BD41-75B4F1D9B96D")]
   public class ApplicationRunner : Runner {
     /// <summary>
     /// Arguments for the StartApplication.
     /// </summary>
+    [Storable]
     public ICommandLineArgument[] Args { get; set; }
 
@@ -15,15 +15,14 @@
     public IApplication StartApplication {
       get {
-        if (application == null) {
-          using (var memStream = new MemoryStream(serializedStartApplication)) {
-            application = (IApplication)formatter.Deserialize(memStream);
-          }
+        lock (locker) {
+          if (application == null)
+            application = (IApplication)new ProtoBufSerializer().Deserialize(serializedStartApplication);
+          return application;
         }
-        return application;
       }
       set {
-        using (var ms = new MemoryStream()) {
-          formatter.Serialize(ms, value);
-          serializedStartApplication = ms.ToArray();
+        lock (locker) {
+          serializedStartApplication = new ProtoBufSerializer().Serialize(value);
+          application = value;
         }
       }
@@ -31,7 +30,10 @@
     // Encapsulated application is necessary, because it is not possible to 
     // instantly deserialize the application, before all assemblies are loaded.
+    [Storable]
     private byte[] serializedStartApplication = new byte[0];
+
     // cache application to prevent new instances every get call of StartApplication
     private IApplication application;
+    private object locker = new object();
 
     protected override void Execute() {
@@ -39,10 +41,11 @@
     }
 
-    protected override void OnRunnerJob(RunnerJob runnerJob) {
-      switch (runnerJob) {
-        case RunnerJob.Cancel: StartApplication.OnCancel(); break;
-        case RunnerJob.Pause: StartApplication.OnPause(); break;
-        case RunnerJob.Resume: StartApplication.OnResume(); break;
-      }
+    protected override void OnRunnerMessage(RunnerMessage message) {
+      if (message is PauseRunnerMessage)
+        StartApplication.OnPause();
+      else if (message is ResumeRunnerMessage)
+        StartApplication.OnResume();
+      else if (message is CancelRunnerMessage)
+        StartApplication.OnCancel();
     }
   }
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/AssemblyInfo.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/AssemblyInfo.cs	(revision 16993)
+++ branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/AssemblyInfo.cs	(revision 17013)
@@ -1,6 +1,6 @@
-﻿using System;
+﻿using HEAL.Attic;
 
 namespace HeuristicLab.PluginInfrastructure {
-  [Serializable]
+  [StorableType(StorableMemberSelection.AllProperties, "D1DC9C3E-16B7-464E-A377-35FA614195AD")]
   public class AssemblyInfo {
     /// <summary>
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/DockerRunnerHost.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/DockerRunnerHost.cs	(revision 16993)
+++ branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/DockerRunnerHost.cs	(revision 17013)
@@ -1,3 +1,5 @@
 ﻿using System.Diagnostics;
+using System.IO;
+using System.Threading.Tasks;
 using HeuristicLab.PluginInfrastructure.Exceptions;
 
@@ -8,25 +10,37 @@
   public class DockerRunnerHost : RunnerHost {
     #region Constants
-    private const string Docker = "docker";
-    private const string ContainerStartup = "container run -i --rm ";
-    private const string Mounting = @"--mount type=bind,source=/c/Users/,target=/Users ";
-    private const string Image = "heuristiclab33:latest";
-    private const string DockerExceptionMessage = "Docker is not running or image '" + Image + "' does not exists!";
+    private readonly static string Docker = "docker";
+    private readonly static string ContainerStartup = "container run -i --rm ";
+    private readonly static string MountingLinux = @"--mount type=bind,source=/c/Users/,target=/Users ";
+    private readonly static string MountingWindows = @"--mount type=bind,source=C:\Users\,target=C:\Users\ ";
+    private readonly static string LinuxImage = "." + Path.DirectorySeparatorChar + "DockerLinuxBuild" + Path.DirectorySeparatorChar + "Dockerfile";
+    private readonly static string WindowsImage = "." + Path.DirectorySeparatorChar + "DockerWindowsBuild" + Path.DirectorySeparatorChar + "Dockerfile";
+    private readonly static string Image = "heuristiclab33:latest";
+    private readonly static string DockerExceptionMessage = "Docker is not running!";
     #endregion
 
     #region Constructors
-    public DockerRunnerHost(bool doDockerAvailableCheck = true)
-      : base(Docker, ContainerStartup + Mounting + Image, null, null, null) {
-      if (doDockerAvailableCheck && !IsDockerAvailable())
-        throw new DockerException(DockerExceptionMessage);
+    public DockerRunnerHost()
+      : base(Docker, ContainerStartup + GetTargetOSMounting() + Image, null, null, null) {
     }
     #endregion
 
     #region Helper
-    private bool IsDockerAvailable() {
+
+    private static string GetTargetOSMounting() {
+      Task<bool> win = Task.Run(() => BuildImage(WindowsImage));
+      Task<bool> lin = Task.Run(() => BuildImage(LinuxImage));
+      if (win.Result) return MountingWindows;
+      else if (lin.Result) return MountingLinux;
+      else throw new DockerException(DockerExceptionMessage);
+    }
+
+    private static bool BuildImage(string pathToDockerfile) {
       var process = new Process {
         StartInfo = new ProcessStartInfo {
           FileName = Docker,
-          Arguments = "image inspect " + Image,
+          Arguments = "image build -t " + Image +
+            " -f " + Path.GetFullPath(pathToDockerfile) +
+            " .",
           UseShellExecute = false,
           RedirectStandardOutput = true,
@@ -37,5 +51,4 @@
         EnableRaisingEvents = false
       };
-
       process.Start();
       process.BeginOutputReadLine();
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/Runner.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/Runner.cs	(revision 16993)
+++ branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/Runner.cs	(revision 17013)
@@ -2,59 +2,65 @@
 using System.Collections.Generic;
 using System.IO;
-using System.Runtime.Serialization;
-using System.Runtime.Serialization.Formatters.Binary;
 using System.Threading;
+using System.Threading.Tasks;
+using HEAL.Attic;
 
 namespace HeuristicLab.PluginInfrastructure {
-  [Serializable]
+  [StorableType(StorableMemberSelection.MarkedOnly, "D93CBE04-9847-417A-AAB5-7FBCA6A32247")]
   public abstract class Runner : IRunner {
 
     #region Vars
-    [NonSerialized]
     private Thread listener;
-
-    [NonSerialized]
-    private Thread executor;
-
-    [NonSerialized]
-    protected static IFormatter formatter = new BinaryFormatter();
     #endregion
 
     #region Properties
-    public bool QuietMode { get; set; }
+    [Storable]
+    public IEnumerable<AssemblyInfo> AssembliesToLoad { get; set; }
 
-    public IEnumerable<AssemblyInfo> AssembliesToLoad { get; set; }
+    internal RunnerHost Host { get; set; }
     #endregion
 
+    public void Pause() {
+      var message = new PauseRunnerMessage();
+      if (Host != null) Host.Send(message);
+      else OnRunnerMessage(message);
+    }
 
-    public static void Serialize(IRunner runner, Stream stream) => formatter.Serialize(stream, runner);
-    public static IRunner Deserialize(Stream stream = null) => (IRunner)formatter.Deserialize(stream);
-    public static void Pause(Stream stream) => formatter.Serialize(stream, RunnerJob.Pause);
-    public static void Resume(Stream stream) => formatter.Serialize(stream, RunnerJob.Resume);
-    public static void Cancel(Stream stream) => formatter.Serialize(stream, RunnerJob.Cancel);
+    public void Resume() {
+      var message = new ResumeRunnerMessage();
+      if (Host != null) Host.Send(message);
+      else OnRunnerMessage(message);
+    }
+
+    public void Cancel() {
+      var message = new CancelRunnerMessage();
+      if (Host != null) Host.Send(message);
+      else OnRunnerMessage(message);
+    }
 
     public void Run() {
       IPluginLoader loader = PluginLoaderFactory.Create();
       loader.LoadPlugins(AssembliesToLoad);
-      StartExecutor();
+      Task t = Task.Run(Execute);
       StartListener();
-      executor.Join();
+      t.Wait();
     }
 
     protected abstract void Execute();
-    protected abstract void OnRunnerJob(RunnerJob runnerJob);
+    protected abstract void OnRunnerMessage(RunnerMessage message);
 
     #region Helper
-    private void StartExecutor() {
-      executor = new Thread(Execute);
-      executor.IsBackground = false;
-      executor.Start();
-    }
 
     private void StartListener() {
       listener = new Thread(() => {
         Stream stdin = Console.OpenStandardInput();
-        while (executor.IsAlive)
-          OnRunnerJob((RunnerJob)formatter.Deserialize(stdin));
+        DateTime lastMessageRecieved = DateTime.MinValue;
+        while (true) {
+          RunnerMessage message = RunnerMessage.ReadMessageFromStream(stdin);
+          if (DateTime.Compare(lastMessageRecieved, message.SendTime) < 0) {
+            OnRunnerMessage(message);
+            lastMessageRecieved = message.SendTime;
+          }
+        }
       });
       listener.IsBackground = true;
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/RunnerHost.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/RunnerHost.cs	(revision 16993)
+++ branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/RunnerHost.cs	(revision 17013)
@@ -4,4 +4,5 @@
 using System.Threading;
 using System.Threading.Tasks;
+using HEAL.Attic;
 
 namespace HeuristicLab.PluginInfrastructure {
@@ -14,6 +15,4 @@
     Starting,
     Running,
-    Paused,
-    Stopping,
     Stopped
   }
@@ -27,7 +26,14 @@
     #region Vars
     protected Process process;
+    private ProtoBufSerializer serializer = new ProtoBufSerializer();
     #endregion
 
     #region Properties
+    /// <summary>
+    /// Set this to true, if console output should be disabled.
+    /// </summary>
+    public bool QuietMode { get; set; }
+
+
     /// <summary>
     /// The programm, which should be used. For example 'docker'.
@@ -41,12 +47,11 @@
     protected string Password { get; private set; }
     protected string Domain { get; private set; }
+    protected IRunner Runner { get; set; }
 
-    /// <summary>
-    /// The runner state.
-    /// </summary>
     public RunnerState State { get; protected set; } = RunnerState.Created;
     #endregion
 
     #region Constructors
+
     protected RunnerHost(string program, string startArgument, string userName, string password, string domain) {
       Program = program;
@@ -63,4 +68,5 @@
         throw new InvalidOperationException("Runner must be in state 'Created'.");
       State = RunnerState.Starting;
+      Runner = runner;
       process = new Process {
         StartInfo = new ProcessStartInfo {
@@ -72,5 +78,5 @@
           RedirectStandardError = true,
           CreateNoWindow = false,
-          UserName = string.IsNullOrEmpty(UserName) ? null : UserName,
+          UserName = string.IsNullOrEmpty(UserName) ? null : UserName, // TODO: accounts testen: https://docs.microsoft.com/en-us/windows/security/identity-protection/access-control/local-accounts#sec-localsystem
           PasswordInClearText = string.IsNullOrEmpty(Password) ? null : Password,
           Domain = string.IsNullOrEmpty(Domain) ? null : Domain,
@@ -80,41 +86,44 @@
       };
       process.Start();
+
       // registers a task for cancellation, prevents the use of polling (while-loop)
       var task = RegisterCancellation(token.HasValue ? token.Value : CancellationToken.None);
 
-      // write config to standardinput, runner listens on this and deserializes the config
-      Runner.Serialize(runner, process.StandardInput.BaseStream);
+      // set runnerhost in runner 
+      Runner r = Runner as Runner;
+      if (r != null) r.Host = this;
 
       process.BeginOutputReadLine();
       process.BeginErrorReadLine();
 
-      if (!runner.QuietMode) {
+      if (!QuietMode) {
         process.OutputDataReceived += (s, e) => Console.WriteLine(e.Data);
         process.ErrorDataReceived += (s, e) => Console.WriteLine(e.Data);
       }
+
+      // write config to standardinput, runner listens on this and deserializes the config
+      SendMessage(new TransportRunnerMessage(Runner));
+
       State = RunnerState.Running;
       if (await task) State = RunnerState.Cancelled;
       else State = RunnerState.Stopped;
-
     }
 
-    /// <summary>
-    /// Pauses the runners. The childprocess gets notified with the help of the standard input and a serialized RunnerJob.
-    /// To pause the runner, the state must be "Running".
-    /// </summary>
-    public void Pause() {
+
+    public void Send(RunnerMessage runnerMessage) {
       if (State != RunnerState.Running) throw new InvalidOperationException("Runner must be in state 'Running'!");
-      Runner.Pause(process.StandardInput.BaseStream);
-      State = RunnerState.Paused;
+      SendMessage(runnerMessage);
     }
 
-    /// <summary>
-    /// Resumes a paused runner. The childprocess gets notified with the help of the standard input and a serialized RunnerJob.
-    /// To resume the runner, the state must be "Paused".
-    /// </summary>
-    public void Resume() {
-      if (State != RunnerState.Paused) throw new InvalidOperationException("Runner must be in state 'Paused'!");
-      Runner.Resume(process.StandardInput.BaseStream);
-      State = RunnerState.Running;
+    // because we need to transfer the runner with a TransportRunnerMessage in the starting state and the 
+    // original send method should not be available until running state
+    protected virtual void SendMessage(RunnerMessage runnerMessage) {
+      runnerMessage.SendTime = DateTime.Now;
+      byte[] bytes = serializer.Serialize(runnerMessage);
+      byte[] size = BitConverter.GetBytes(bytes.Length);
+      process.StandardInput.BaseStream.Write(size, 0, size.Length);
+      process.StandardInput.BaseStream.Flush();
+      process.StandardInput.BaseStream.Write(bytes, 0, bytes.Length);
+      process.StandardInput.BaseStream.Flush();
     }
 
@@ -125,5 +134,5 @@
     /// When the child process gets finished without requested cancellation, the linked token gets cancelled and a result set. 
     /// </summary>
-    private Task<bool> RegisterCancellation(CancellationToken token) {
+    protected Task<bool> RegisterCancellation(CancellationToken token) {
       if (process != null && State == RunnerState.Starting) {
         var cts = CancellationTokenSource.CreateLinkedTokenSource(token);
@@ -133,5 +142,5 @@
         cts.Token.Register(() => {
           if (!process.HasExited) {
-            Runner.Cancel(process.StandardInput.BaseStream);
+            Runner.Cancel();
             process.WaitForExit();
           }
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/RunnerJob.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/RunnerJob.cs	(revision 16993)
+++ 	(revision )
@@ -1,16 +1,0 @@
-﻿using System;
-using System.IO;
-using System.Runtime.Serialization;
-using System.Runtime.Serialization.Formatters.Binary;
-
-namespace HeuristicLab.PluginInfrastructure {
-  /// <summary>
-  /// Job command for the runner.
-  /// </summary>
-  [Serializable]
-  public enum RunnerJob {
-    Cancel,
-    Pause,
-    Resume
-  }
-}
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/RunnerMessage.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/RunnerMessage.cs	(revision 17013)
+++ branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/RunnerMessage.cs	(revision 17013)
@@ -0,0 +1,48 @@
+﻿using System;
+using System.IO;
+using HEAL.Attic;
+
+namespace HeuristicLab.PluginInfrastructure {
+
+  [StorableType(StorableMemberSelection.MarkedOnly, "081DC79E-1E57-49A2-AB25-D9AC42A40911")]
+  public class RunnerMessage {
+    private static ProtoBufSerializer serializer = new ProtoBufSerializer();
+    public static RunnerMessage ReadMessageFromStream(Stream stream) {
+      byte[] buf = new byte[4];
+      stream.Read(buf, 0, buf.Length);
+      int bufSize = BitConverter.ToInt32(buf, 0);
+      buf = new byte[bufSize];
+      stream.Read(buf, 0, buf.Length);
+      return (RunnerMessage)serializer.Deserialize(buf);
+    }
+
+    /// <summary>
+    /// This will get set from the RunnerHost and helps to identify the correct message flow.
+    /// </summary>
+    [Storable]
+    public DateTime SendTime { get; set; }
+  }
+
+
+  [StorableType(StorableMemberSelection.AllProperties, "84771CF3-46CA-4D0B-96D1-7F2E8EAC50B7")]
+  public class PauseRunnerMessage : RunnerMessage { }
+
+
+  [StorableType(StorableMemberSelection.AllProperties, "FE2AEE66-E2A2-4DE1-8E60-C116F084D2AA")]
+  public class ResumeRunnerMessage : RunnerMessage { }
+
+
+  [StorableType(StorableMemberSelection.AllProperties, "2C836B74-C28B-4F4A-9645-E1ED5F4415A7")]
+  public class CancelRunnerMessage : RunnerMessage { }
+
+
+  [StorableType(StorableMemberSelection.AllProperties, "2D8D1D8F-58D4-4D92-BB15-62DF55DC0459")]
+  public class TransportRunnerMessage : RunnerMessage {
+    public IRunner Runner { get; set; }
+    public TransportRunnerMessage(IRunner runner) => Runner = runner;
+
+    [StorableConstructor]
+    private TransportRunnerMessage(StorableConstructorFlag _) { }
+  }
+
+}
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Utils/UniPath.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Utils/UniPath.cs	(revision 16993)
+++ branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Utils/UniPath.cs	(revision 17013)
@@ -1,30 +1,31 @@
-﻿using System;
-using System.Collections.Generic;
-using System.IO;
+﻿using System.IO;
 using System.Runtime.InteropServices;
-using System.Text;
 using System.Text.RegularExpressions;
+using HEAL.Attic;
 
 namespace HeuristicLab.PluginInfrastructure {
-  [Serializable]
+  [StorableType("8911C8DC-FDA0-4CF6-A0CD-C67E72094D62")]
   public class UniPath {
 
     #region Vars
+    [Storable]
     private string fullPath = "";
     #endregion
 
     #region Constructors
+    [StorableConstructor]
+    private UniPath(StorableConstructorFlag _) { }
     public UniPath(string path) {
       fullPath = Path.GetFullPath(path);
     }
     #endregion
-    
+
     private bool IsWindowsAbsolutePath(string path) => Regex.IsMatch(path, @"^[A-Z]:");
-    
+
     private string Rebuild(char split, string startStr, string seperator) {
       string[] splits = fullPath.Split(split);
       string tmp = startStr;
       int i = 1;
-      while (i < splits.Length - 1) {
+      while (i < (splits.Length - 1)) {
         tmp += splits[i] + seperator;
         ++i;
