Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/ApplicationBase.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/ApplicationBase.cs	(revision 16859)
+++ branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/ApplicationBase.cs	(revision 16984)
@@ -21,8 +21,11 @@
 
 
+using System;
+
 namespace HeuristicLab.PluginInfrastructure {
   /// <summary>
   /// Abstract base implementation for the IApplication interface.
   /// </summary>
+  [Serializable]
   public abstract class ApplicationBase : IApplication {
     /// <summary>
@@ -69,4 +72,8 @@
     public abstract void Run(ICommandLineArgument[] args);
 
+    public virtual void OnCancel() { Console.WriteLine("OnCancellation"); }
+    public virtual void OnPause() { Console.WriteLine("OnPause"); }
+    public virtual void OnResume() { Console.WriteLine("OnResume"); }
+
     #endregion
   }
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/ApplicationDescription.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/ApplicationDescription.cs	(revision 16859)
+++ branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/ApplicationDescription.cs	(revision 16984)
@@ -26,5 +26,5 @@
   /// Class that provides information about an application.
   /// </summary>
-  [Serializable]
+  /*[Serializable]
   public sealed class ApplicationDescription : IApplicationDescription {
     private string name;
@@ -86,4 +86,4 @@
       return Name + " " + Version;
     }
-  }
+  }*/
 }
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/AssemblyExtensions.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/AssemblyExtensions.cs	(revision 16859)
+++ 	(revision )
@@ -1,63 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2015 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 System;
-using System.Reflection;
-
-namespace HeuristicLab.PluginInfrastructure {
-  public static class AssemblyExtensions {
-    //Based on the code from http://stackoverflow.com/a/7156425
-    public static string GetCustomAttributeValue<T>(this Assembly assembly, string propertyName)
-       where T : Attribute {
-      if (assembly == null || string.IsNullOrEmpty(propertyName)) {
-        throw new ArgumentException("Arguments are not allowed to be null.");
-      }
-
-      object[] attributes = assembly.GetCustomAttributes(typeof(T), false);
-      if (attributes.Length == 0) {
-        throw new InvalidOperationException(string.Format("No attributes of type {0} found in assembly {1}", typeof(T).Name,
-          assembly.FullName));
-      }
-
-      var attribute = (T)attributes[0];
-      var propertyInfo = attribute.GetType().GetProperty(propertyName);
-      if (propertyInfo == null) {
-        throw new InvalidOperationException(string.Format("No property {0} found in attribute {1}, assembly: {2}",
-          propertyName, typeof(T).Name, assembly.FullName));
-      }
-
-      var value = propertyInfo.GetValue(attribute, null);
-      return value.ToString();
-    }
-
-    public static string GetFileVersion(this Assembly assembly) {
-      return GetCustomAttributeValue<AssemblyFileVersionAttribute>(assembly, "Version");
-    }
-    public static string GetCopyright(this Assembly assembly) {
-      return GetCustomAttributeValue<AssemblyCopyrightAttribute>(assembly, "Copyright");
-    }
-
-    public static string GetProduct(this Assembly assembly) {
-      return GetCustomAttributeValue<AssemblyProductAttribute>(assembly, "Product");
-    }
-
-  }
-}
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/DockerRunner.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/DockerRunner.cs	(revision 16859)
+++ 	(revision )
@@ -1,39 +1,0 @@
-﻿using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.IO;
-using System.Text;
-
-namespace HeuristicLab.PluginInfrastructure {
-  public class DockerRunner : IRunner {
-
-    private Process process;
-    public void Start(string basePath, string[] args) {
-      string arguments =
-        $"run -i --rm --mount type=bind,source=/,target=/app/ dockerrunner -- " +
-        $"--basePath /app{basePath} -- ";
-      foreach (string s in args) arguments += s + " ";
-      process = new Process {
-        StartInfo = new ProcessStartInfo {
-          FileName = "docker",
-          Arguments = arguments,
-          UseShellExecute = false,
-          RedirectStandardOutput = true,
-          RedirectStandardInput = true,
-          RedirectStandardError = true,
-          CreateNoWindow = false
-        }
-      };
-      process.Start();
-      process.BeginOutputReadLine();
-      process.BeginErrorReadLine();
-      process.OutputDataReceived += (s, e) => Console.WriteLine(e.Data);
-      process.ErrorDataReceived += (s, e) => Console.WriteLine(e.Data);
-    }
-
-    public void Stop() {
-      process.WaitForExit();
-      process.Close();
-    }
-  }
-}
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Dockerfile
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Dockerfile	(revision 16859)
+++ 	(revision )
@@ -1,12 +1,0 @@
-﻿FROM microsoft/dotnet:2.2-sdk
-
-# copy and build everything else
-COPY ./HeuristicLab.PluginInfrastructure/3.3/ ./HeuristicLab.PluginInfrastructure/3.3/
-COPY ./HeuristicLab.PluginInfrastructure.Runner ./HeuristicLab.PluginInfrastructure.Runner/
-COPY ./HeuristicLab.Tracing/3.3/ ./HeuristicLab.Tracing/3.3/
-
-WORKDIR /HeuristicLab.PluginInfrastructure.Runner
-
-
-RUN dotnet publish -c Release -o out
-ENTRYPOINT ["dotnet", "out/HeuristicLab.PluginInfrastructure.Runner.dll"]
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Exceptions/InvalidPluginException.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Exceptions/InvalidPluginException.cs	(revision 16984)
+++ branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Exceptions/InvalidPluginException.cs	(revision 16984)
@@ -0,0 +1,53 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 System;
+using System.Runtime.Serialization;
+
+namespace HeuristicLab.PluginInfrastructure {
+  /// <summary>
+  /// Exception class for invalid plugins.
+  /// </summary>
+  [Serializable]
+  public sealed class InvalidPluginException : Exception {
+    /// <summary>
+    /// Initializes a new InvalidPluginException
+    /// </summary>
+    public InvalidPluginException() : base() { }
+    /// <summary>
+    /// Initializes a new InvalidPluginException with an error message.
+    /// </summary>
+    /// <param name="message">The exception message</param>
+    public InvalidPluginException(string message) : base(message) { }
+    /// <summary>
+    /// Initializes a new InvalidPluginException with an error message and an inner exception.
+    /// </summary>
+    /// <param name="message">The exception message.</param>
+    /// <param name="innerException">The original exception.</param>
+    public InvalidPluginException(string message, Exception innerException) : base(message, innerException) { }
+    /// <summary>
+    /// Constructor for serialization.
+    /// </summary>
+    /// <param name="info">The serialization info.</param>
+    /// <param name="contex">The serialization context.</param>
+    private InvalidPluginException(SerializationInfo info, StreamingContext contex) : base(info, contex) { }
+  }
+}
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 16859)
+++ branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/HeuristicLab.PluginInfrastructure-3.3.csproj	(revision 16984)
@@ -19,4 +19,5 @@
     <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.ServiceModel.Primitives" Version="4.5.3" />
@@ -24,3 +25,6 @@
     <PackageReference Include="System.Security.Cryptography.Primitives" Version="4.3.0" />
   </ItemGroup>
+  <ItemGroup>
+    <Folder Include="Exceptions\" />
+  </ItemGroup>
 </Project>
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Interfaces/IActivator.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Interfaces/IActivator.cs	(revision 16859)
+++ 	(revision )
@@ -1,18 +1,0 @@
-﻿using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace HeuristicLab.PluginInfrastructure {
-  /// <summary>
-  /// Classes from type IActivator gets automatically searched and activated with the method "Activate".
-  /// </summary>
-  public interface IActivator {
-    /// <summary>
-    /// The entry point of an IActivator.
-    /// </summary>
-    /// <param name="context"></param>
-    /// <param name="args"></param>
-    void Activate(IActivatorContext context, string[] args);
-    void Stop(IActivatorContext context);
-  }
-}
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Interfaces/IActivatorContext.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Interfaces/IActivatorContext.cs	(revision 16859)
+++ 	(revision )
@@ -1,22 +1,0 @@
-﻿using System;
-using System.Collections.Generic;
-using System.Text;
-using HeuristicLab.PluginInfrastructure;
-
-namespace HeuristicLab.PluginInfrastructure {
-  /// <summary>
-  /// Interface for a ActivatorContext implementation.
-  /// </summary>
-  public interface IActivatorContext {
-    /// <summary>
-    /// Returns all plugins found by a PluginLoader.
-    /// </summary>
-    IList<IPlugin> Plugins { get; }
-
-    /// <summary>
-    /// Returns all applications found by a PluginLoader.
-    /// </summary>
-    IList<IApplication> Applications { get; }
-
-  }
-}
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Interfaces/IApplication.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Interfaces/IApplication.cs	(revision 16859)
+++ branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Interfaces/IApplication.cs	(revision 16984)
@@ -38,4 +38,19 @@
     /// </summary>
     void Run(ICommandLineArgument[] args);
+
+    /// <summary>
+    /// This method gets called when a cancellation is invoked.
+    /// </summary>
+    void OnCancel();
+
+    /// <summary>
+    /// This method gets called when a pause is invoked.
+    /// </summary>
+    void OnPause();
+
+    /// <summary>
+    /// This method gets called when a resume is invoked.
+    /// </summary>
+    void OnResume();
   }
 }
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Interfaces/IApplicationManager.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Interfaces/IApplicationManager.cs	(revision 16859)
+++ branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Interfaces/IApplicationManager.cs	(revision 16984)
@@ -52,4 +52,11 @@
     /// <returns>An enumerable of instances of the discovered types.</returns>
     IEnumerable<object> GetInstances(Type type);
+
+    /// <summary>
+    /// Discovers a specific type by its name.
+    /// </summary>
+    /// <param name="typeName">Full name of the type.</param>
+    /// <returns>A type or null, if nothing was found.</returns>
+    Type GetType(string typeName);
 
     /// <summary>
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Interfaces/IAssemblyLoader.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Interfaces/IAssemblyLoader.cs	(revision 16859)
+++ branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Interfaces/IAssemblyLoader.cs	(revision 16984)
@@ -2,14 +2,15 @@
 using System.Collections.Generic;
 using System.Reflection;
-using System.Text;
 
 namespace HeuristicLab.PluginInfrastructure {
+  /// <summary>
+  /// Interface for an assembly loading mechanism
+  /// </summary>
   public interface IAssemblyLoader {
-    string BasePath { get; set; }
-
     /// <summary>
     /// Returns all loaded assemblies.
     /// </summary>
     IEnumerable<Assembly> Assemblies { get; }
+
     /// <summary>
     /// Returns all types.
@@ -18,16 +19,16 @@
 
     /// <summary>
-    /// Returns all assemblies included in BasePath. 
+    /// Loads all assemblies (.dll/.exe) in the specified path.
     /// </summary>
-    /// <returns></returns>
-    IEnumerable<Assembly> GetReflectionOnlyAssemblies();
+    /// <param name="basePath">Path to root directory of all assemblies to load.</param>
+    /// <returns>An IEnumerable of assemblies.</returns>
+    IEnumerable<Assembly> LoadAssemblies(string basePath);
 
     /// <summary>
-    /// Loads all assembliesm which are given by the assemblyName argument, into the current context. 
+    /// Loads all specified assemblies.
     /// </summary>
-    /// <param name="assemblyNames"></param>
-    /// <returns>All loaded assemblies.</returns>
-    IEnumerable<Assembly> LoadAssemblies(IEnumerable<AssemblyName> assemblyNames);
-
+    /// <param name="assemblyInfos">Infos for all assemblies to load.</param>
+    /// <returns>An IEnumerable of assemblies.</returns>
+    IEnumerable<Assembly> LoadAssemblies(IEnumerable<AssemblyInfo> assemblyInfos);
   }
 }
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Interfaces/IPluginLoader.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Interfaces/IPluginLoader.cs	(revision 16859)
+++ branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Interfaces/IPluginLoader.cs	(revision 16984)
@@ -1,23 +1,31 @@
-﻿using System;
-using System.Collections.Generic;
-using System.Text;
-using HeuristicLab.PluginInfrastructure;
+﻿using System.Collections.Generic;
 
 namespace HeuristicLab.PluginInfrastructure {
+  /// <summary>
+  /// Interface for a plugin load mechanism.
+  /// </summary>
   public interface IPluginLoader {
-    /// <summary>
-    /// Returns all activators found.
-    /// </summary>
-    IList<IActivator> Activators { get; }
-
     /// <summary>
     /// Returns all plugins found.
     /// </summary>
-    IList<IPlugin> Plugins { get; }
+    IEnumerable<IPlugin> Plugins { get; }
 
     /// <summary>
     /// Returns all Applications found.
     /// </summary>
-    IList<IApplication> Applications { get; }
+    IEnumerable<IApplication> Applications { get; }
+
+    /// <summary>
+    /// Load plugins, definied by the given AssemblyInfos.
+    /// </summary>
+    /// <param name="assemblyInfos">AssemblyInfos for the assemblies, which should be loaded.</param>
+    void LoadPlugins(IEnumerable<AssemblyInfo> assemblyInfos);
+
+    /// <summary>
+    /// Searches for .dll/.exe files and validates them.
+    /// </summary>
+    /// <param name="basePath">Path of the root directory for the assemblies to validate.</param>
+    /// <returns>A IEnumerable of AssemblyInfos, which contains all loadable assemblies. </returns>
+    IEnumerable<AssemblyInfo> Validate(string basePath);
   }
 }
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Interfaces/IRunner.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Interfaces/IRunner.cs	(revision 16859)
+++ branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Interfaces/IRunner.cs	(revision 16984)
@@ -1,21 +1,23 @@
 ﻿using System;
 using System.Collections.Generic;
+using System.IO;
 using System.Text;
 
 namespace HeuristicLab.PluginInfrastructure {
-
-  /// <summary>
-  /// Interface for all runner implementations.
-  /// </summary>
   public interface IRunner {
     /// <summary>
-    /// Method to start the runner which scans all assemblies in the given basePath argument. 
-    /// Additionally, arguments can be specified, which are forwarded to all activators.
+    /// Set this to true, if console output should be disabled.
     /// </summary>
-    /// <param name="basePath"></param>
-    /// <param name="args"></param>
-    void Start(string basePath, string[] args);
+    bool QuietMode { get; set; }
 
-    void Stop();
+    /// <summary>
+    /// Assemblies which the child process needs to load.
+    /// </summary>
+    IEnumerable<AssemblyInfo> AssembliesToLoad { get; set; }
+
+    /// <summary>
+    /// Method to run the runner.
+    /// </summary>
+    void Run();
   }
 }
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/InvalidPluginException.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/InvalidPluginException.cs	(revision 16859)
+++ 	(revision )
@@ -1,53 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2018 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 System;
-using System.Runtime.Serialization;
-
-namespace HeuristicLab.PluginInfrastructure {
-  /// <summary>
-  /// Exception class for invalid plugins.
-  /// </summary>
-  [Serializable]
-  public sealed class InvalidPluginException : Exception {
-    /// <summary>
-    /// Initializes a new InvalidPluginException
-    /// </summary>
-    public InvalidPluginException() : base() { }
-    /// <summary>
-    /// Initializes a new InvalidPluginException with an error message.
-    /// </summary>
-    /// <param name="message">The exception message</param>
-    public InvalidPluginException(string message) : base(message) { }
-    /// <summary>
-    /// Initializes a new InvalidPluginException with an error message and an inner exception.
-    /// </summary>
-    /// <param name="message">The exception message.</param>
-    /// <param name="innerException">The original exception.</param>
-    public InvalidPluginException(string message, Exception innerException) : base(message, innerException) { }
-    /// <summary>
-    /// Constructor for serialization.
-    /// </summary>
-    /// <param name="info">The serialization info.</param>
-    /// <param name="contex">The serialization context.</param>
-    private InvalidPluginException(SerializationInfo info, StreamingContext contex) : base(info, contex) { }
-  }
-}
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/ApplicationRunner.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/ApplicationRunner.cs	(revision 16984)
+++ branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/ApplicationRunner.cs	(revision 16984)
@@ -0,0 +1,46 @@
+﻿using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+namespace HeuristicLab.PluginInfrastructure {
+  [Serializable]
+  public class ApplicationRunner : Runner {
+    /// <summary>
+    /// Arguments for the StartApplication.
+    /// </summary>
+    public ICommandLineArgument[] Args { get; set; }
+
+    /// <summary>
+    /// The application which should run in child process.
+    /// </summary>
+    public IApplication StartApplication {
+      get {
+        using (var memStream = new MemoryStream(serializedStartApplication)) {
+          return (IApplication)formatter.Deserialize(memStream);
+        }
+      }
+      set {
+        using (var ms = new MemoryStream()) {
+          formatter.Serialize(ms, value);
+          serializedStartApplication = ms.ToArray();
+        }
+      }
+    }
+    // Encapsulated application is necessary, because it is not possible to 
+    // instantly deserialize the application, before all assemblies are loaded.
+    private byte[] serializedStartApplication = new byte[0];
+
+    protected override void Execute() {
+      StartApplication.Run(Args);
+    }
+
+    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;
+      }
+    }
+  }
+}
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/AssemblyInfo.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/AssemblyInfo.cs	(revision 16984)
+++ branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/AssemblyInfo.cs	(revision 16984)
@@ -0,0 +1,16 @@
+﻿using System;
+
+namespace HeuristicLab.PluginInfrastructure {
+  [Serializable]
+  public class AssemblyInfo {
+    /// <summary>
+    /// Path to the assembly file.
+    /// </summary>
+    public UniPath Path { get; set; } = null;
+
+    /// <summary>
+    /// Fullname of the assembly.
+    /// </summary>
+    public string Name { get; set; }
+  }
+}
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/AssemblyLoader.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/AssemblyLoader.cs	(revision 16984)
+++ branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/AssemblyLoader.cs	(revision 16984)
@@ -0,0 +1,176 @@
+﻿using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.Loader;
+
+namespace HeuristicLab.PluginInfrastructure {
+
+  /// <summary>
+  /// Class to load assemblies.
+  /// </summary>
+  public class AssemblyLoader : IAssemblyLoader {
+    /// <summary>
+    /// Comparer for AssemblyNames.
+    /// </summary>
+    private class AssemblyNameComparer : IEqualityComparer<AssemblyName> {
+      private object concatProps(AssemblyName name) => name.FullName + name.Version.ToString();
+      public bool Equals(AssemblyName lhs, AssemblyName rhs) => concatProps(lhs).Equals(concatProps(rhs));
+      public int GetHashCode(AssemblyName obj) => concatProps(obj).GetHashCode();
+    }
+
+    #region Vars
+    private readonly IList<Assembly> assemblies = new List<Assembly>();
+    private readonly IList<Type> types = new List<Type>();
+    #endregion
+
+    #region Properties
+    /// <summary>
+    /// All loaded assemblies. Contains items only after a call of LoadAssemblies.
+    /// </summary>
+    public IEnumerable<Assembly> Assemblies => assemblies;
+
+    /// <summary>
+    /// All types found in all assemblies.
+    /// </summary>
+    public IEnumerable<Type> Types => types;
+    #endregion
+
+    #region Constructors
+    public AssemblyLoader() {
+
+      #region alternative code
+      /*
+      ScanTypesInBasePath();
+      Types = GetTypes();
+      */
+      /*
+      IEnumerable<Assembly> asms = CheckDependencies(GetLoadableAssemblies(GetAssembliesFromBasePath()));
+      LoadAssemblies(asms);
+      LoadTypes(asms);
+      */
+      //IEnumerable<Assembly> asms = GetLoadableAssemblies(GetAssembliesFromBasePath());
+      //LoadAssemblies(asms);
+      //LoadTypes(asms);
+      #endregion
+    }
+    #endregion
+
+
+    private IEnumerable<string> GetAssembliesFromBasePath(string basePath) {
+      return Directory.GetFiles(basePath, "*.dll", SearchOption.AllDirectories)
+        .Concat(Directory.GetFiles(basePath, "*.exe", SearchOption.AllDirectories));
+    }
+
+    #region alternative code
+    /*
+    // 2.
+    private IEnumerable<Assembly> GetLoadableAssemblies(IEnumerable<string> paths) {
+      IList<Assembly> assemblies = new List<Assembly>();      
+      foreach (string path in paths) {
+        try {
+          var asm = Assembly.LoadFile(path);
+          if (asm != null)
+            assemblies.Add(asm);
+          else
+            Console.WriteLine($"cannot load assembly with path={path}");
+        } catch (Exception e) {
+          Console.WriteLine($"exception occured for assembly with path={path}, type of exception={e.GetType()}");
+        }
+      }
+      
+      return assemblies;
+    }
+    
+    // 3.
+    private IEnumerable<Assembly> CheckDependencies(IEnumerable<Assembly> assemblies) {
+      IEqualityComparer<AssemblyName> comp = new AssemblyNameComparer();
+      IDictionary<AssemblyName, Assembly> dict = new Dictionary<AssemblyName, Assembly>(comp);
+
+      // fill dict
+      foreach (Assembly a in assemblies)
+        dict.Add(a.GetName(), a);
+
+      Parallel.ForEach(new List<Assembly>(dict.Values), asm => {
+        if (CheckDependencyRecursiveHelper(asm.GetName(), asm.GetReferencedAssemblies(), comp, dict))
+          lock(dict)
+            dict.Remove(asm.GetName());
+      });
+      return dict.Values;
+    }
+
+    private bool CheckDependencyRecursiveHelper(AssemblyName toCheck, IEnumerable<AssemblyName> refs, IEqualityComparer<AssemblyName> comp, IDictionary<AssemblyName, Assembly> dict) {
+      foreach(AssemblyName name in refs) {
+        if (comp.Equals(toCheck, name) || !dict.ContainsKey(name) || CheckDependencyRecursiveHelper(toCheck, dict[name].GetReferencedAssemblies(), comp, dict)) return true;
+      }
+      return false;
+    }
+    
+    // 4.
+    private void LoadAssemblies(IEnumerable<Assembly> assemblies) {
+
+      foreach (Assembly asm in assemblies) {
+        try {
+          Assemblies.Add(alc.LoadFromAssemblyName(asm.GetName()));
+        } catch(Exception e) { }
+      }
+    }
+    */
+    #endregion
+
+
+    private void LoadTypes(IEnumerable<Assembly> assemblies) {
+      foreach (Assembly asm in assemblies) {
+        try {
+          foreach (Type t in asm.GetExportedTypes()) {
+            types.Add(t);
+          }
+        } catch (ReflectionTypeLoadException e) {
+          // ReflectionTypeLoadException gets thrown if any class in a module cannot be loaded.
+          try {
+            foreach (Type t in e.Types) { // fetch the already loaded types, be careful some of them can be null
+              if (t != null) {
+                types.Add(t);
+              }
+            }
+          } catch (BadImageFormatException) { }
+        } catch (Exception e) { // to catch every other exception
+          //Tracing.Logger.Error(
+          //  $"Exception occured while loading types of assembly {asm.FullName}! \n " +
+          //  $"---- Stacktrace ---- \n {e}");
+        }
+      }
+    }
+
+    public IEnumerable<Assembly> LoadAssemblies(string basePath) {
+      foreach (string path in GetAssembliesFromBasePath(basePath))
+        LoadAssemblyFromPath(path);
+      
+      LoadTypes(this.Assemblies);
+      return this.Assemblies;
+    }
+
+    public IEnumerable<Assembly> LoadAssemblies(IEnumerable<AssemblyInfo> assemblyInfos) {
+      foreach (var info in assemblyInfos)
+        LoadAssemblyFromPath(info.Path.ToString());
+      
+      LoadTypes(this.Assemblies);
+      return this.Assemblies;
+    }
+
+    private void LoadAssemblyFromPath(string path) {
+      try {
+        var asm = AssemblyLoadContext.Default.LoadFromAssemblyPath(path); // loads assembly into default context
+        if (asm != null) {
+          assemblies.Add(asm);
+        } // else
+          //Tracing.Logger.Error($"Unnable to load assembly with path {path}!");
+      } catch (Exception e) { // to catch every exception occured by assembly loading.
+        //Tracing.Logger.Error(
+        //  $"Exception occured while loading assembly from path {path}! \n " +
+        //  $"---- Stacktrace ---- \n {e}");
+      }
+    }
+  }
+}
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/DockerRunnerHost.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/DockerRunnerHost.cs	(revision 16984)
+++ branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/DockerRunnerHost.cs	(revision 16984)
@@ -0,0 +1,10 @@
+﻿namespace HeuristicLab.PluginInfrastructure {
+  /// <summary>
+  /// IRunner for isolation with docker.
+  /// </summary>
+  public class DockerRunnerHost : RunnerHost {
+    public DockerRunnerHost()
+      : base("docker", "run -i --rm --mount type=bind,source=/c/Users/,target=/Users hlcore", null, null, null) {
+    }
+  }
+}
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/NativeRunnerHost.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/NativeRunnerHost.cs	(revision 16984)
+++ branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/NativeRunnerHost.cs	(revision 16984)
@@ -0,0 +1,12 @@
+﻿using System.IO;
+
+namespace HeuristicLab.PluginInfrastructure {
+  /// <summary>
+  /// IRunner for isolation with a native process.
+  /// </summary>
+  public class NativeRunnerHost : RunnerHost {
+    public NativeRunnerHost()
+      : base($"{Directory.GetCurrentDirectory()}{Path.DirectorySeparatorChar}HLCore.exe", "", null, null, null) {
+    }
+  }
+}
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/PluginLoader.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/PluginLoader.cs	(revision 16984)
+++ branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/PluginLoader.cs	(revision 16984)
@@ -0,0 +1,455 @@
+﻿using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Security;
+using System.Text;
+
+namespace HeuristicLab.PluginInfrastructure {
+  public class PluginLoader : IPluginLoader {
+
+    /// <summary>
+    /// Helper class for depedency metadata.
+    /// </summary>
+    private class PluginDependency {
+      public string Name { get; private set; }
+      public Version Version { get; private set; }
+      public PluginDependency(string name, Version version) {
+        this.Name = name;
+        this.Version = version;
+      }
+    }
+
+    #region Vars
+    private IList<IPlugin> plugins = new List<IPlugin>();
+    private IList<IApplication> applications = new List<IApplication>();
+    private IAssemblyLoader assemblyLoader = null;
+    private Dictionary<PluginDescription, IEnumerable<PluginDependency>> pluginDependencies = new Dictionary<PluginDescription, IEnumerable<PluginDependency>>();
+    #endregion
+
+    #region Properties
+    public IEnumerable<IPlugin> Plugins => plugins;
+
+    public IEnumerable<IApplication> Applications => applications;
+    #endregion
+
+    #region Constructors
+    public PluginLoader(IAssemblyLoader assemblyLoader) {
+      this.assemblyLoader = assemblyLoader;
+    }
+    #endregion
+
+    #region Discover Methods
+    public void LoadPlugins(IEnumerable<AssemblyInfo> assemblyInfos) {
+      assemblyLoader.LoadAssemblies(assemblyInfos);
+      DiscoverPlugins();
+      DiscoverApplications();
+    }
+    /// <summary>
+    /// Discovers all types of IPlugin of all loaded assemblies. Saves the found plugins in a list.
+    /// </summary>
+    private void DiscoverPlugins() {
+      // search plugins out of all types
+      string curDir = Directory.GetCurrentDirectory(); // save current working directory
+      foreach (var type in assemblyLoader.Types) {
+        if (typeof(IPlugin).IsAssignableFrom(type) && !type.IsAbstract && !type.IsInterface && !type.HasElementType) {
+          // to set the working directory to the assembly location, this is necessary for assemblies which load data in the OnLoad method by their own.
+          // example: HeuristicLabMathJaxPlugin
+          Directory.SetCurrentDirectory(type.Assembly.Location.Replace(Path.GetFileName(type.Assembly.Location), ""));
+          IPlugin p = (IPlugin)Activator.CreateInstance(type);
+          p.OnLoad();
+          plugins.Add(p);
+        }
+      }
+      Directory.SetCurrentDirectory(curDir); // set working directory to its base value
+    }
+
+    /// <summary>
+    /// Discovers all types of IApplication of all loaded assemblies. Saves the found applications in a list.
+    /// </summary>
+    private void DiscoverApplications() {
+      foreach (Type type in assemblyLoader.Types) {
+        if (typeof(IApplication).IsAssignableFrom(type) && !type.IsAbstract && !type.IsInterface && !type.HasElementType) {
+          IApplication app = (IApplication)Activator.CreateInstance(type);
+          applications.Add(app);
+        }
+      }
+    }
+    #endregion
+       
+    public IEnumerable<AssemblyInfo> Validate(string basePath) {
+      IEnumerable<Assembly> assemblies = assemblyLoader.LoadAssemblies(basePath);
+
+      IList<PluginDescription> pluginDescriptions = GatherPluginDescriptions(assemblies, basePath);
+      CheckPluginFiles(pluginDescriptions, basePath);
+
+      // check if all plugin assemblies can be loaded
+      CheckPluginAssemblies(assemblies, pluginDescriptions);
+
+      // a full list of plugin descriptions is available now we can build the dependency tree
+      BuildDependencyTree(pluginDescriptions);
+
+      // check for dependency cycles
+      CheckPluginDependencyCycles(pluginDescriptions);
+
+      // 1st time recursively check if all necessary plugins are available and not disabled
+      // disable plugins with missing or disabled dependencies 
+      // to prevent that plugins with missing dependencies are loaded into the execution context
+      // in the next step
+      CheckPluginDependencies(pluginDescriptions);
+
+      // build assemblyInfo list: 
+      // 1.) iterate through pluginDescriptions and pick all not disabled plugins
+      // 2.) iterate through the assemblyLocations, saved in a description
+      // 3.) iterate thorugh all loaded assemblies 
+      // 4.) if the location of an assemblies and a pluginDescriptions match -> create new AssemblyInfo and add it to a list
+      IList<AssemblyInfo> list = new List<AssemblyInfo>();
+      foreach (var desc in pluginDescriptions) {
+        if (desc.PluginState != PluginState.Disabled) {
+          foreach (var loc in desc.AssemblyLocations) {
+            foreach (var asm in assemblies) {
+              if (string.Equals(Path.GetFullPath(asm.Location), Path.GetFullPath(loc), StringComparison.CurrentCultureIgnoreCase))
+                list.Add(new AssemblyInfo() { Path = new UniPath(asm.Location), Name = asm.FullName });
+            }
+          }
+        }
+      }
+
+      return list;
+    }
+
+    #region oldCode
+    /// <summary>
+    /// Checks if all plugin assemblies can be loaded. If an assembly can't be loaded the plugin is disabled.
+    /// </summary>
+    /// <param name="pluginDescriptions"></param>
+    private void CheckPluginAssemblies(IEnumerable<Assembly> assemblies, IEnumerable<PluginDescription> pluginDescriptions) {
+      foreach (var desc in pluginDescriptions.Where(x => x.PluginState != PluginState.Disabled)) {
+        try {
+          var missingAssemblies = new List<string>();
+          foreach (var asmLocation in desc.AssemblyLocations) {
+            // the assembly must have been loaded in ReflectionOnlyDlls
+            // so we simply determine the name of the assembly and try to find it in the cache of loaded assemblies
+            var asmName = AssemblyName.GetAssemblyName(asmLocation);
+            if (!assemblies.Select(x => x.GetName().FullName).Contains(asmName.FullName)) {
+              missingAssemblies.Add(asmName.FullName);
+            }
+          }
+          if (missingAssemblies.Count > 0) {
+            StringBuilder errorStrBuiler = new StringBuilder();
+            errorStrBuiler.AppendLine("Missing assemblies:");
+            foreach (string missingAsm in missingAssemblies) {
+              errorStrBuiler.AppendLine(missingAsm);
+            }
+            desc.Disable(errorStrBuiler.ToString());
+          }
+        } catch (BadImageFormatException ex) {
+          // disable the plugin
+          desc.Disable("Problem while loading plugin assemblies:" + Environment.NewLine + "BadImageFormatException: " + ex.Message);
+        } catch (FileNotFoundException ex) {
+          // disable the plugin
+          desc.Disable("Problem while loading plugin assemblies:" + Environment.NewLine + "FileNotFoundException: " + ex.Message);
+        } catch (FileLoadException ex) {
+          // disable the plugin
+          desc.Disable("Problem while loading plugin assemblies:" + Environment.NewLine + "FileLoadException: " + ex.Message);
+        } catch (ArgumentException ex) {
+          // disable the plugin
+          desc.Disable("Problem while loading plugin assemblies:" + Environment.NewLine + "ArgumentException: " + ex.Message);
+        } catch (SecurityException ex) {
+          // disable the plugin
+          desc.Disable("Problem while loading plugin assemblies:" + Environment.NewLine + "SecurityException: " + ex.Message);
+        }
+      }
+    }
+
+
+    // find all types implementing IPlugin in the reflectionOnlyAssemblies and create a list of plugin descriptions
+    // the dependencies in the plugin descriptions are not yet set correctly because we need to create
+    // the full list of all plugin descriptions first
+    private IList<PluginDescription> GatherPluginDescriptions(IEnumerable<Assembly> assemblies, string basePath) {
+      List<PluginDescription> pluginDescriptions = new List<PluginDescription>();
+      foreach (Assembly assembly in assemblies) {
+        // GetExportedTypes throws FileNotFoundException when a referenced assembly
+        // of the current assembly is missing.
+        try {
+          // if there is a type that implements IPlugin
+          // use AssemblyQualifiedName to compare the types because we can't directly 
+          // compare ReflectionOnly types and execution types
+
+          var assemblyPluginDescriptions = from t in assembly.GetExportedTypes()
+                                           where !t.IsAbstract && t.GetInterfaces()
+                                           .Any(x => x.AssemblyQualifiedName == typeof(IPlugin).AssemblyQualifiedName)
+                                           select GetPluginDescription(t, basePath);
+          pluginDescriptions.AddRange(assemblyPluginDescriptions);
+        }
+        // ignore exceptions. Just don't yield a plugin description when an exception is thrown
+        catch (FileNotFoundException) {
+        } catch (FileLoadException) {
+        } catch (InvalidPluginException) {
+        } catch (TypeLoadException) {
+        } catch (MissingMemberException) {
+        }
+      }
+      return pluginDescriptions;
+    }
+
+    // checks if all declared plugin files are actually available and disables plugins with missing files
+    private void CheckPluginFiles(IEnumerable<PluginDescription> pluginDescriptions, string basePath) {
+      foreach (PluginDescription desc in pluginDescriptions) {
+        IEnumerable<string> missingFiles;
+        if (ArePluginFilesMissing(desc, basePath, out missingFiles)) {
+          StringBuilder errorStrBuilder = new StringBuilder();
+          errorStrBuilder.AppendLine("Missing files:");
+          foreach (string fileName in missingFiles) {
+            errorStrBuilder.AppendLine(fileName);
+          }
+          desc.Disable(errorStrBuilder.ToString());
+        }
+      }
+    }
+
+    private bool ArePluginFilesMissing(PluginDescription pluginDescription, string basePath, out IEnumerable<string> missingFiles) {
+      List<string> missing = new List<string>();
+      foreach (string filename in pluginDescription.Files.Select(x => x.Name)) {
+        if (!FileLiesInDirectory(basePath, filename) ||
+          !File.Exists(filename)) {
+          missing.Add(filename);
+        }
+      }
+      missingFiles = missing;
+      return missing.Count > 0;
+    }
+
+    private static bool FileLiesInDirectory(string dir, string fileName) {
+      var basePath = Path.GetFullPath(dir);
+      return Path.GetFullPath(fileName).StartsWith(basePath);
+    }
+
+    /// <summary>
+    /// Extracts plugin information for this type.
+    /// Reads plugin name, list and type of files and dependencies of the plugin. This information is necessary for
+    /// plugin dependency checking before plugin activation.
+    /// </summary>
+    /// <param name="pluginType"></param>
+    private PluginDescription GetPluginDescription(Type pluginType, string basePath) {
+
+      string pluginName, pluginDescription, pluginVersion;
+      string contactName, contactAddress;
+      GetPluginMetaData(pluginType, out pluginName, out pluginDescription, out pluginVersion);
+      GetPluginContactMetaData(pluginType, out contactName, out contactAddress);
+      var pluginFiles = GetPluginFilesMetaData(pluginType, basePath);
+      var pluginDependencies = GetPluginDependencyMetaData(pluginType);
+
+      // minimal sanity check of the attribute values
+      if (!string.IsNullOrEmpty(pluginName) &&
+          pluginFiles.Count() > 0 &&                                 // at least one file
+          pluginFiles.Any(f => f.Type == PluginFileType.Assembly)) { // at least one assembly
+        // create a temporary PluginDescription that contains the attribute values
+        PluginDescription info = new PluginDescription();
+        info.Name = pluginName;
+        info.Description = pluginDescription;
+        info.Version = new Version(pluginVersion);
+        info.ContactName = contactName;
+        info.ContactEmail = contactAddress;
+        info.LicenseText = ReadLicenseFiles(pluginFiles);
+        info.AddFiles(pluginFiles);
+
+        this.pluginDependencies[info] = pluginDependencies;
+        return info;
+      } else {
+        throw new InvalidPluginException("Invalid metadata in plugin " + pluginType.ToString());
+      }
+    }
+
+    private string ReadLicenseFiles(IEnumerable<PluginFile> pluginFiles) {
+      // combine the contents of all plugin files 
+      var licenseFiles = from file in pluginFiles
+                         where file.Type == PluginFileType.License
+                         select file;
+      if (licenseFiles.Count() == 0) return string.Empty;
+      StringBuilder licenseTextBuilder = new StringBuilder();
+      licenseTextBuilder.AppendLine(File.ReadAllText(licenseFiles.First().Name));
+      foreach (var licenseFile in licenseFiles.Skip(1)) {
+        licenseTextBuilder.AppendLine().AppendLine(); // leave some empty space between multiple license files
+        licenseTextBuilder.AppendLine(File.ReadAllText(licenseFile.Name));
+      }
+      return licenseTextBuilder.ToString();
+    }
+
+    private static IEnumerable<PluginDependency> GetPluginDependencyMetaData(Type pluginType) {
+      // get all attributes of type PluginDependency
+      var dependencyAttributes = pluginType.GetCustomAttributes<PluginDependencyAttribute>();
+      /*from attr in CustomAttributeData.GetCustomAttributes(pluginType)
+                               where IsAttributeDataForType(attr, typeof(PluginDependencyAttribute))
+                               select attr;*/
+      foreach (var dependencyAttr in dependencyAttributes) {
+        string name = (string)dependencyAttr.Dependency; //ConstructorArguments[0].Value;
+        Version version = new Version("0.0.0.0"); // default version
+        // check if version is given for now
+        // later when the constructor of PluginDependencyAttribute with only one argument has been removed
+        // this conditional can be removed as well
+        if (dependencyAttr.Version != null) {
+          try {
+            version = dependencyAttr.Version;//new Version((string)dependencyAttr.ConstructorArguments[1].Value); // might throw FormatException
+          } catch (FormatException ex) {
+            throw new InvalidPluginException("Invalid version format of dependency " + name + " in plugin " + pluginType.ToString(), ex);
+          }
+        }
+        yield return new PluginDependency(name, version);
+      }
+    }
+
+    private static void GetPluginContactMetaData(Type pluginType, out string contactName, out string contactAddress) {
+      // get attribute of type ContactInformation if there is any
+      var contactInfoAttribute = (from attr in CustomAttributeData.GetCustomAttributes(pluginType)
+                                  where IsAttributeDataForType(attr, typeof(ContactInformationAttribute))
+                                  select attr).SingleOrDefault();
+
+      if (contactInfoAttribute != null) {
+        contactName = (string)contactInfoAttribute.ConstructorArguments[0].Value;
+        contactAddress = (string)contactInfoAttribute.ConstructorArguments[1].Value;
+      } else {
+        contactName = string.Empty;
+        contactAddress = string.Empty;
+      }
+    }
+
+    // not static because we need the BasePath property
+    private IEnumerable<PluginFile> GetPluginFilesMetaData(Type pluginType, string basePath) {
+      // get all attributes of type PluginFileAttribute
+      var pluginFileAttributes = from attr in CustomAttributeData.GetCustomAttributes(pluginType)
+                                 where IsAttributeDataForType(attr, typeof(PluginFileAttribute))
+                                 select attr;
+      foreach (var pluginFileAttribute in pluginFileAttributes) {
+        string pluginFileName = (string)pluginFileAttribute.ConstructorArguments[0].Value;
+        PluginFileType fileType = (PluginFileType)pluginFileAttribute.ConstructorArguments[1].Value;
+        yield return new PluginFile(Path.GetFullPath(Path.Combine(basePath, pluginFileName)), fileType);
+      }
+    }
+
+    private static void GetPluginMetaData(Type pluginType, out string pluginName, out string pluginDescription, out string pluginVersion) {
+      // there must be a single attribute of type PluginAttribute
+      var pluginMetaDataAttr = (from attr in CustomAttributeData.GetCustomAttributes(pluginType)
+                                where IsAttributeDataForType(attr, typeof(PluginAttribute))
+                                select attr).Single();
+
+      pluginName = (string)pluginMetaDataAttr.ConstructorArguments[0].Value;
+
+      // default description and version
+      pluginVersion = "0.0.0.0";
+      pluginDescription = string.Empty;
+      if (pluginMetaDataAttr.ConstructorArguments.Count() == 2) {
+        // if two arguments are given the second argument is the version
+        pluginVersion = (string)pluginMetaDataAttr.ConstructorArguments[1].Value;
+      } else if (pluginMetaDataAttr.ConstructorArguments.Count() == 3) {
+        // if three arguments are given the second argument is the description and the third is the version
+        pluginDescription = (string)pluginMetaDataAttr.ConstructorArguments[1].Value;
+        pluginVersion = (string)pluginMetaDataAttr.ConstructorArguments[2].Value;
+      }
+    }
+
+
+    private static bool IsAttributeDataForType(CustomAttributeData attributeData, Type attributeType) {
+      return attributeData.Constructor.DeclaringType.AssemblyQualifiedName == attributeType.AssemblyQualifiedName;
+    }
+
+    // builds a dependency tree of all plugin descriptions
+    // searches matching plugin descriptions based on the list of dependency names for each plugin
+    // and sets the dependencies in the plugin descriptions
+    private void BuildDependencyTree(IEnumerable<PluginDescription> pluginDescriptions) {
+      foreach (var desc in pluginDescriptions.Where(x => x.PluginState != PluginState.Disabled)) {
+        var missingDependencies = new List<PluginDependency>();
+        foreach (var dependency in pluginDependencies[desc]) {
+          var matchingDescriptions = from availablePlugin in pluginDescriptions
+                                     where availablePlugin.PluginState != PluginState.Disabled
+                                     where availablePlugin.Name == dependency.Name
+                                     where IsCompatiblePluginVersion(availablePlugin.Version, dependency.Version)
+                                     select availablePlugin;
+          if (matchingDescriptions.Count() > 0) {
+            desc.AddDependency(matchingDescriptions.First());
+          } else {
+            missingDependencies.Add(dependency);
+          }
+        }
+        // no plugin description that matches the dependencies are available => plugin is disabled
+        if (missingDependencies.Count > 0) {
+          StringBuilder errorStrBuilder = new StringBuilder();
+          errorStrBuilder.AppendLine("Missing dependencies:");
+          foreach (var missingDep in missingDependencies) {
+            errorStrBuilder.AppendLine(missingDep.Name + " " + missingDep.Version);
+          }
+          desc.Disable(errorStrBuilder.ToString());
+        }
+      }
+    }
+
+    /// <summary>
+    /// Checks if version <paramref name="available"/> is compatible to version <paramref name="requested"/>.
+    /// Note: the compatibility relation is not bijective.
+    /// Compatibility rules:
+    ///  * major and minor number must be the same
+    ///  * build and revision number of <paramref name="available"/> must be larger or equal to <paramref name="requested"/>.
+    /// </summary>
+    /// <param name="available">The available version which should be compared to <paramref name="requested"/>.</param>
+    /// <param name="requested">The requested version that must be matched.</param>
+    /// <returns></returns>
+    private static bool IsCompatiblePluginVersion(Version available, Version requested) {
+      // this condition must be removed after all plugins have been updated to declare plugin and dependency versions
+      if (
+        (requested.Major == 0 && requested.Minor == 0) ||
+        (available.Major == 0 && available.Minor == 0)) return true;
+      return
+        available.Major == requested.Major &&
+        available.Minor == requested.Minor &&
+        available.Build >= requested.Build &&
+        available.Revision >= requested.Revision;
+    }
+
+    private void CheckPluginDependencyCycles(IEnumerable<PluginDescription> pluginDescriptions) {
+      foreach (var plugin in pluginDescriptions) {
+        // if the plugin is not disabled check if there are cycles
+        if (plugin.PluginState != PluginState.Disabled && HasCycleInDependencies(plugin, plugin.Dependencies)) {
+          plugin.Disable("Dependency graph has a cycle.");
+        }
+      }
+    }
+
+    private bool HasCycleInDependencies(PluginDescription plugin, IEnumerable<PluginDescription> pluginDependencies) {
+      foreach (var dep in pluginDependencies) {
+        // if one of the dependencies is the original plugin we found a cycle and can return
+        // if the dependency is already disabled we can ignore the cycle detection because we will disable the plugin anyway
+        // if following one of the dependencies recursively leads to a cycle then we also return
+        if (dep == plugin || dep.PluginState == PluginState.Disabled || HasCycleInDependencies(plugin, dep.Dependencies)) return true;
+      }
+      // no cycle found and none of the direct and indirect dependencies is disabled
+      return false;
+    }
+
+    private void CheckPluginDependencies(IEnumerable<PluginDescription> pluginDescriptions) {
+      foreach (PluginDescription pluginDescription in pluginDescriptions.Where(x => x.PluginState != PluginState.Disabled)) {
+        List<PluginDescription> disabledPlugins = new List<PluginDescription>();
+        if (IsAnyDependencyDisabled(pluginDescription, disabledPlugins)) {
+          StringBuilder errorStrBuilder = new StringBuilder();
+          errorStrBuilder.AppendLine("Dependencies are disabled:");
+          foreach (var disabledPlugin in disabledPlugins) {
+            errorStrBuilder.AppendLine(disabledPlugin.Name + " " + disabledPlugin.Version);
+          }
+          pluginDescription.Disable(errorStrBuilder.ToString());
+        }
+      }
+    }
+
+    private bool IsAnyDependencyDisabled(PluginDescription descr, List<PluginDescription> disabledPlugins) {
+      if (descr.PluginState == PluginState.Disabled) {
+        disabledPlugins.Add(descr);
+        return true;
+      }
+      foreach (PluginDescription dependency in descr.Dependencies) {
+        IsAnyDependencyDisabled(dependency, disabledPlugins);
+      }
+      return disabledPlugins.Count > 0;
+    }
+  }
+  #endregion
+}
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/PluginLoaderFactory.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/PluginLoaderFactory.cs	(revision 16984)
+++ branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/PluginLoaderFactory.cs	(revision 16984)
@@ -0,0 +1,18 @@
+﻿using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+namespace HeuristicLab.PluginInfrastructure {
+  /// <summary>
+  /// Factory to create an instance of a plugin loader. 
+  /// </summary>
+  public static class PluginLoaderFactory {
+    /// <summary>
+    /// Creates a new instance of a plugin loader.
+    /// </summary>
+    public static IPluginLoader Create() {
+      return new PluginLoader(new AssemblyLoader());
+    }
+  }
+}
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/Runner.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/Runner.cs	(revision 16984)
+++ branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/Runner.cs	(revision 16984)
@@ -0,0 +1,59 @@
+﻿using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Runtime.Serialization;
+using System.Runtime.Serialization.Formatters.Binary;
+using System.Text;
+using System.Threading;
+
+namespace HeuristicLab.PluginInfrastructure {
+  [Serializable]
+  public abstract class Runner : IRunner {
+
+    [NonSerialized]
+    private Thread listener;
+
+    [NonSerialized]
+    private Thread executor;
+
+    [NonSerialized]
+    protected static IFormatter formatter = new BinaryFormatter();
+    
+    public bool QuietMode { get; set; }
+     
+    public IEnumerable<AssemblyInfo> AssembliesToLoad { get; set; }
+
+    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 Run() {
+      IPluginLoader loader = PluginLoaderFactory.Create();
+      loader.LoadPlugins(AssembliesToLoad);
+      StartExecutor();
+      StartListener();
+      executor.Join();
+    }
+
+    protected abstract void Execute();
+    protected abstract void OnRunnerJob(RunnerJob runnerJob);
+
+    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));
+      });
+      listener.IsBackground = true;
+      listener.Start();
+    }
+
+  }
+}
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/RunnerHost.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/RunnerHost.cs	(revision 16984)
+++ branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/RunnerHost.cs	(revision 16984)
@@ -0,0 +1,146 @@
+﻿using System;
+using System.Diagnostics;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace HeuristicLab.PluginInfrastructure {
+  /// <summary>
+  /// Enum for the different RunnerStates.
+  /// </summary>
+  public enum RunnerState {
+    Created,
+    Cancelled,
+    Starting,
+    Running,
+    Paused,
+    Stopping,
+    Stopped
+  }
+
+  /// <summary>
+  /// Abstract <c>RunnerBase</c> class, which implements the IRunner interface. 
+  /// Every specific runner implementation should inherit this class.
+  /// </summary>
+  public abstract class RunnerHost : IRunnerHost {
+
+    #region Vars
+    protected Process process;
+    #endregion
+
+    #region Properties
+    /// <summary>
+    /// The programm, which should be used. For example 'docker'.
+    /// </summary>
+    protected string Program { get; private set; }
+    /// <summary>
+    /// The specific start arguments for the programm.
+    /// </summary>
+    protected string StartArgument { get; private set; }
+    protected string UserName { get; private set; }
+    protected string Password { get; private set; }
+    protected string Domain { get; private 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;
+      StartArgument = startArgument + " --StartAsRunnerHost";
+      UserName = userName;
+      Password = password;
+      Domain = domain;
+    }
+    #endregion
+
+    public virtual void Run(IRunner runner) => RunAsync(runner, null).Wait();
+    public virtual async Task RunAsync(IRunner runner, CancellationToken? token = null) {
+      if (State != RunnerState.Created)
+        throw new InvalidOperationException("Runner must be in state 'Created'.");
+      State = RunnerState.Starting;
+      process = new Process {
+        StartInfo = new ProcessStartInfo {
+          FileName = Program,
+          Arguments = StartArgument,
+          UseShellExecute = false,
+          RedirectStandardOutput = true,
+          RedirectStandardInput = true,
+          RedirectStandardError = true,
+          CreateNoWindow = false,
+          UserName = string.IsNullOrEmpty(UserName) ? null : UserName,
+          PasswordInClearText = string.IsNullOrEmpty(Password) ? null : Password,
+          Domain = string.IsNullOrEmpty(Domain) ? null: Domain,
+          WorkingDirectory = Directory.GetCurrentDirectory()
+        },
+        EnableRaisingEvents = true
+      };
+      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);
+
+      if (!runner.QuietMode) {
+        process.BeginOutputReadLine();
+        process.BeginErrorReadLine();
+        process.OutputDataReceived += (s, e) => Console.WriteLine(e.Data);
+        process.ErrorDataReceived += (s, e) => Console.WriteLine(e.Data);
+      }
+      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() {
+      if (State != RunnerState.Running) throw new InvalidOperationException("Runner must be in state 'Running'!");
+      Runner.Pause(process.StandardInput.BaseStream);
+      State = RunnerState.Paused;
+    }
+
+    /// <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;
+    }
+
+    /// <summary>
+    /// Creates a new LinkedTokenSource and a TaskCompletionSource. 
+    /// When the specified token gets cancelled, a cancel requests gets send to the childprocess. 
+    /// Afterwards the main process waits for the exit of the child process and sets a result of the TaskCompletionSource.
+    /// When the child process gets finished without requested cancellation, the linked token gets cancelled and a result set. 
+    /// </summary>
+    /// <param name="token"></param>
+    /// <returns></returns>
+    private Task<bool> RegisterCancellation(CancellationToken token) {
+      if (process != null && State == RunnerState.Starting) {
+        var cts = CancellationTokenSource.CreateLinkedTokenSource(token);
+        var tcs = new TaskCompletionSource<bool>();
+
+        process.Exited += (s, e) => cts.Cancel();
+        cts.Token.Register(() => {
+          if (!process.HasExited) {
+            Runner.Cancel(process.StandardInput.BaseStream);
+            process.WaitForExit();
+          }
+          tcs.SetResult(token.IsCancellationRequested);
+        });
+        return tcs.Task;
+      }
+      return null;
+    }
+  }
+}
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/RunnerJob.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/RunnerJob.cs	(revision 16984)
+++ branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/RunnerJob.cs	(revision 16984)
@@ -0,0 +1,16 @@
+﻿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/LightweightApplicationManager.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/LightweightApplicationManager.cs	(revision 16859)
+++ branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/LightweightApplicationManager.cs	(revision 16984)
@@ -75,9 +75,16 @@
       foreach (Type t in GetTypes(type)) {
         object instance = null;
-        try { instance = Activator.CreateInstance(t); }
-        catch { }
+        try { instance = Activator.CreateInstance(t); } catch { }
         if (instance != null) instances.Add(instance);
       }
       return instances;
+    }
+
+    public Type GetType(string typeName) {
+      foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) {
+        Type t = asm.GetType(typeName);
+        if (t != null) return t;
+      }
+      return null;
     }
 
@@ -126,4 +133,5 @@
         // necessary to make sure the exception is immediately thrown
         // instead of later when the enumerable is iterated?
+
         var assemblyTypes = assembly.GetTypes();
 
@@ -138,9 +146,7 @@
 
         return matchingTypes;
-      }
-      catch (TypeLoadException) {
+      } catch (TypeLoadException) {
         return Enumerable.Empty<Type>();
-      }
-      catch (ReflectionTypeLoadException) {
+      } catch (ReflectionTypeLoadException) {
         return Enumerable.Empty<Type>();
       }
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/NativProcessRunner.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/NativProcessRunner.cs	(revision 16859)
+++ 	(revision )
@@ -1,43 +1,0 @@
-﻿using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.IO;
-using System.Text;
-
-namespace HeuristicLab.PluginInfrastructure {
-  public class NativProcessRunner : IRunner {
-
-    private Process process;
-
-    public void Start(string basePath,  string[] args) {
-
-      string arguments = 
-        $"{Directory.GetCurrentDirectory()}{Path.DirectorySeparatorChar}" +
-        $"HeuristicLab.PluginInfrastructure.Runner-3.4.dll -- " +
-        $"--basePath {basePath} -- ";
-      foreach (string s in args) arguments += s + " ";
-
-      process = new Process {
-        StartInfo = new ProcessStartInfo {
-          FileName = "dotnet",
-          Arguments = arguments,
-          UseShellExecute = false,
-          RedirectStandardOutput = true,
-          RedirectStandardInput = true,
-          RedirectStandardError = true,
-          CreateNoWindow = false
-        }
-      };
-      process.Start();
-      process.BeginOutputReadLine();
-      process.BeginErrorReadLine();
-      process.OutputDataReceived += (s, e) => Console.WriteLine(e.Data);
-      process.ErrorDataReceived += (s, e) => Console.WriteLine(e.Data);
-    }
-
-    public void Stop() {
-      process.WaitForExit();
-      process.Close();
-    }
-  }
-}
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/PluginDescriptionIterator.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/PluginDescriptionIterator.cs	(revision 16859)
+++ 	(revision )
@@ -1,66 +1,0 @@
-#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2018 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 System.Collections.Generic;
-using System.Linq;
-
-namespace HeuristicLab.PluginInfrastructure {
-  public static class PluginDescriptionIterator {
-    public static IEnumerable<PluginDescription> IterateDependenciesBottomUp(IEnumerable<PluginDescription> pluginDescriptions) {
-      // list to make sure we yield each description only once
-      HashSet<PluginDescription> yieldedDescriptions = new HashSet<PluginDescription>();
-      foreach (var desc in pluginDescriptions) {
-        foreach (var dependency in IterateDependenciesBottomUp(desc.Dependencies)) {
-          if (!yieldedDescriptions.Contains(dependency)) {
-            yieldedDescriptions.Add(dependency);
-            yield return dependency;
-          }
-        }
-        if (!yieldedDescriptions.Contains(desc)) {
-          yieldedDescriptions.Add(desc);
-          yield return desc;
-        }
-      }
-    }
-
-    public static IEnumerable<PluginDescription> IterateDependentsTopDown(IEnumerable<PluginDescription> pluginDescriptions, IEnumerable<PluginDescription> allPlugins) {
-      HashSet<PluginDescription> yieldedDescriptions = new HashSet<PluginDescription>();
-      foreach (var desc in pluginDescriptions) {
-        foreach (var dependent in IterateDependentsTopDown(GetDependentPlugins(desc, allPlugins), allPlugins)) {
-          if (!yieldedDescriptions.Contains(dependent)) {
-            yieldedDescriptions.Add(dependent);
-            yield return dependent;
-          }
-        }
-        if (!yieldedDescriptions.Contains(desc)) {
-          yieldedDescriptions.Add(desc);
-          yield return desc;
-        }
-      }
-    }
-
-    private static IEnumerable<PluginDescription> GetDependentPlugins(PluginDescription desc, IEnumerable<PluginDescription> allPlugins) {
-      return from plugin in allPlugins
-             where plugin.Dependencies.Contains(desc)
-             select plugin;
-    }
-  }
-}
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/PluginInfrastructureEventArgs.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/PluginInfrastructureEventArgs.cs	(revision 16859)
+++ 	(revision )
@@ -1,37 +1,0 @@
-#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2015 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 System;
-
-namespace HeuristicLab.PluginInfrastructure {
-  [Serializable]
-  public sealed class PluginInfrastructureEventArgs : EventArgs {
-    public object Entity { get; private set; }
-    public PluginInfrastructureEventArgs(object entity) {
-      this.Entity = entity;
-    }
-
-    private static PluginInfrastructureEventArgs emptyArgs = new PluginInfrastructureEventArgs(string.Empty);
-    public new static PluginInfrastructureEventArgs Empty {
-      get { return emptyArgs; }
-    }
-  }
-}
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/TypeExtensions.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/TypeExtensions.cs	(revision 16859)
+++ 	(revision )
@@ -1,129 +1,0 @@
-﻿#region License Information
-
-/* HeuristicLab
- * Copyright (C) 2002-2018 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 System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-
-namespace HeuristicLab.PluginInfrastructure {
-  internal static class TypeExtensions {
-    internal static bool IsNonDiscoverableType(this Type t) {
-      return t.GetCustomAttributes(typeof(NonDiscoverableTypeAttribute), false).Any();
-    }
-
-    /// <summary>
-    /// Constructs a concrete type from a given proto type.
-    /// </summary>
-    /// <param name="type"></param>
-    /// <param name="protoType"></param>
-    /// <returns>The constructed type, a generic type definition or null, if a type construction is not possible</returns>
-    /// <remarks>This method does not work with nested generic types</remarks>
-    internal static Type BuildType(this Type type, Type protoType) {
-      if (type == null || protoType == null) throw new ArgumentNullException();
-
-      if (!type.IsGenericTypeDefinition) return type;
-      if (protoType.IsGenericTypeDefinition) return type;
-      if (!protoType.IsGenericType) return type;
-
-      var typeGenericArguments = type.GetGenericArguments();
-      var protoTypeGenericArguments = protoType.GetGenericArguments();
-      if (typeGenericArguments.Length != protoTypeGenericArguments.Length) return null;
-
-      for (int i = 0; i < typeGenericArguments.Length; i++) {
-        var typeGenericArgument = typeGenericArguments[i];
-        var protoTypeGenericArgument = protoTypeGenericArguments[i];
-
-        //check class contraint on generic type parameter 
-        if (typeGenericArgument.GenericParameterAttributes.HasFlag(GenericParameterAttributes.ReferenceTypeConstraint))
-          if (!protoTypeGenericArgument.IsClass && !protoTypeGenericArgument.IsInterface && !protoType.IsArray) return null;
-
-        //check default constructor constraint on generic type parameter 
-        if (typeGenericArgument.GenericParameterAttributes.HasFlag(GenericParameterAttributes.DefaultConstructorConstraint))
-          if (!protoTypeGenericArgument.IsValueType && protoTypeGenericArgument.GetConstructor(Type.EmptyTypes) == null) return null;
-
-        //check type restrictions on generic type parameter
-        foreach (var constraint in typeGenericArgument.GetGenericParameterConstraints())
-          if (!constraint.IsAssignableFrom(protoTypeGenericArgument)) return null;
-      }
-
-      try {
-        return type.MakeGenericType(protoTypeGenericArguments);
-      }
-      catch (Exception) {
-        return null;
-      }
-    }
-
-    internal static bool IsSubTypeOf(this Type subType, Type baseType) {
-      if (baseType.IsAssignableFrom(subType)) return true;
-      if (!baseType.IsGenericType) return false;
-
-      if (RecursiveCheckGenericTypes(baseType, subType)) return true;
-      IEnumerable<Type> implementedInterfaces = subType.GetInterfaces().Where(t => t.IsGenericType);
-      foreach (var implementedInterface in implementedInterfaces.Where(i => i.IsGenericType)) {
-        if (baseType.CheckGenericTypes(implementedInterface)) return true;
-      }
-
-      return false;
-    }
-
-    private static bool RecursiveCheckGenericTypes(Type baseType, Type subType) {
-      if (!baseType.IsGenericType) return false;
-      if (!subType.IsGenericType) return false;
-      if (baseType.CheckGenericTypes(subType)) return true;
-      if (subType.BaseType == null) return false;
-
-      return RecursiveCheckGenericTypes(baseType, subType.BaseType);
-    }
-
-    private static bool CheckGenericTypes(this Type baseType, Type subType) {
-      var baseTypeGenericTypeDefinition = baseType.GetGenericTypeDefinition();
-      var subTypeGenericTypeDefinition = subType.GetGenericTypeDefinition();
-      if (baseTypeGenericTypeDefinition != subTypeGenericTypeDefinition) return false;
-      var baseTypeGenericArguments = baseType.GetGenericArguments();
-      var subTypeGenericArguments = subType.GetGenericArguments();
-
-      for (int i = 0; i < baseTypeGenericArguments.Length; i++) {
-        var baseTypeGenericArgument = baseTypeGenericArguments[i];
-        var subTypeGenericArgument = subTypeGenericArguments[i];
-
-        if (baseTypeGenericArgument.IsGenericParameter ^ subTypeGenericArgument.IsGenericParameter) return false;
-        if (baseTypeGenericArgument == subTypeGenericArgument) continue;
-        if (!baseTypeGenericArgument.IsGenericParameter && !subTypeGenericArgument.IsGenericParameter) return false;
-
-        if (baseTypeGenericArgument.GenericParameterAttributes.HasFlag(GenericParameterAttributes.ReferenceTypeConstraint) &&
-            !subTypeGenericArgument.GenericParameterAttributes.HasFlag(GenericParameterAttributes.ReferenceTypeConstraint)) return false;
-        if (baseTypeGenericArgument.GenericParameterAttributes.HasFlag(GenericParameterAttributes.DefaultConstructorConstraint) &&
-            !subTypeGenericArgument.GenericParameterAttributes.HasFlag(GenericParameterAttributes.DefaultConstructorConstraint)) return false;
-        if (baseTypeGenericArgument.GenericParameterAttributes.HasFlag(GenericParameterAttributes.NotNullableValueTypeConstraint) &&
-            !subTypeGenericArgument.GenericParameterAttributes.HasFlag(GenericParameterAttributes.NotNullableValueTypeConstraint)) return false;
-
-        foreach (var baseTypeGenericParameterConstraint in baseTypeGenericArgument.GetGenericParameterConstraints()) {
-          if (!subTypeGenericArgument.GetGenericParameterConstraints().Any(t => baseTypeGenericParameterConstraint.IsAssignableFrom(t))) return false;
-        }
-      }
-      return true;
-    }
-  }
-}
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Utils/AssemblyExtensions.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Utils/AssemblyExtensions.cs	(revision 16984)
+++ branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Utils/AssemblyExtensions.cs	(revision 16984)
@@ -0,0 +1,63 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 System;
+using System.Reflection;
+
+namespace HeuristicLab.PluginInfrastructure {
+  public static class AssemblyExtensions {
+    //Based on the code from http://stackoverflow.com/a/7156425
+    public static string GetCustomAttributeValue<T>(this Assembly assembly, string propertyName)
+       where T : Attribute {
+      if (assembly == null || string.IsNullOrEmpty(propertyName)) {
+        throw new ArgumentException("Arguments are not allowed to be null.");
+      }
+
+      object[] attributes = assembly.GetCustomAttributes(typeof(T), false);
+      if (attributes.Length == 0) {
+        throw new InvalidOperationException(string.Format("No attributes of type {0} found in assembly {1}", typeof(T).Name,
+          assembly.FullName));
+      }
+
+      var attribute = (T)attributes[0];
+      var propertyInfo = attribute.GetType().GetProperty(propertyName);
+      if (propertyInfo == null) {
+        throw new InvalidOperationException(string.Format("No property {0} found in attribute {1}, assembly: {2}",
+          propertyName, typeof(T).Name, assembly.FullName));
+      }
+
+      var value = propertyInfo.GetValue(attribute, null);
+      return value.ToString();
+    }
+
+    public static string GetFileVersion(this Assembly assembly) {
+      return GetCustomAttributeValue<AssemblyFileVersionAttribute>(assembly, "Version");
+    }
+    public static string GetCopyright(this Assembly assembly) {
+      return GetCustomAttributeValue<AssemblyCopyrightAttribute>(assembly, "Copyright");
+    }
+
+    public static string GetProduct(this Assembly assembly) {
+      return GetCustomAttributeValue<AssemblyProductAttribute>(assembly, "Product");
+    }
+
+  }
+}
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Utils/TypeExtensions.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Utils/TypeExtensions.cs	(revision 16984)
+++ branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Utils/TypeExtensions.cs	(revision 16984)
@@ -0,0 +1,129 @@
+﻿#region License Information
+
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace HeuristicLab.PluginInfrastructure {
+  internal static class TypeExtensions {
+    internal static bool IsNonDiscoverableType(this Type t) {
+      return t.GetCustomAttributes(typeof(NonDiscoverableTypeAttribute), false).Any();
+    }
+
+    /// <summary>
+    /// Constructs a concrete type from a given proto type.
+    /// </summary>
+    /// <param name="type"></param>
+    /// <param name="protoType"></param>
+    /// <returns>The constructed type, a generic type definition or null, if a type construction is not possible</returns>
+    /// <remarks>This method does not work with nested generic types</remarks>
+    internal static Type BuildType(this Type type, Type protoType) {
+      if (type == null || protoType == null) throw new ArgumentNullException();
+
+      if (!type.IsGenericTypeDefinition) return type;
+      if (protoType.IsGenericTypeDefinition) return type;
+      if (!protoType.IsGenericType) return type;
+
+      var typeGenericArguments = type.GetGenericArguments();
+      var protoTypeGenericArguments = protoType.GetGenericArguments();
+      if (typeGenericArguments.Length != protoTypeGenericArguments.Length) return null;
+
+      for (int i = 0; i < typeGenericArguments.Length; i++) {
+        var typeGenericArgument = typeGenericArguments[i];
+        var protoTypeGenericArgument = protoTypeGenericArguments[i];
+
+        //check class contraint on generic type parameter 
+        if (typeGenericArgument.GenericParameterAttributes.HasFlag(GenericParameterAttributes.ReferenceTypeConstraint))
+          if (!protoTypeGenericArgument.IsClass && !protoTypeGenericArgument.IsInterface && !protoType.IsArray) return null;
+
+        //check default constructor constraint on generic type parameter 
+        if (typeGenericArgument.GenericParameterAttributes.HasFlag(GenericParameterAttributes.DefaultConstructorConstraint))
+          if (!protoTypeGenericArgument.IsValueType && protoTypeGenericArgument.GetConstructor(Type.EmptyTypes) == null) return null;
+
+        //check type restrictions on generic type parameter
+        foreach (var constraint in typeGenericArgument.GetGenericParameterConstraints())
+          if (!constraint.IsAssignableFrom(protoTypeGenericArgument)) return null;
+      }
+
+      try {
+        return type.MakeGenericType(protoTypeGenericArguments);
+      }
+      catch (Exception) {
+        return null;
+      }
+    }
+
+    internal static bool IsSubTypeOf(this Type subType, Type baseType) {
+      if (baseType.IsAssignableFrom(subType)) return true;
+      if (!baseType.IsGenericType) return false;
+
+      if (RecursiveCheckGenericTypes(baseType, subType)) return true;
+      IEnumerable<Type> implementedInterfaces = subType.GetInterfaces().Where(t => t.IsGenericType);
+      foreach (var implementedInterface in implementedInterfaces.Where(i => i.IsGenericType)) {
+        if (baseType.CheckGenericTypes(implementedInterface)) return true;
+      }
+
+      return false;
+    }
+
+    private static bool RecursiveCheckGenericTypes(Type baseType, Type subType) {
+      if (!baseType.IsGenericType) return false;
+      if (!subType.IsGenericType) return false;
+      if (baseType.CheckGenericTypes(subType)) return true;
+      if (subType.BaseType == null) return false;
+
+      return RecursiveCheckGenericTypes(baseType, subType.BaseType);
+    }
+
+    private static bool CheckGenericTypes(this Type baseType, Type subType) {
+      var baseTypeGenericTypeDefinition = baseType.GetGenericTypeDefinition();
+      var subTypeGenericTypeDefinition = subType.GetGenericTypeDefinition();
+      if (baseTypeGenericTypeDefinition != subTypeGenericTypeDefinition) return false;
+      var baseTypeGenericArguments = baseType.GetGenericArguments();
+      var subTypeGenericArguments = subType.GetGenericArguments();
+
+      for (int i = 0; i < baseTypeGenericArguments.Length; i++) {
+        var baseTypeGenericArgument = baseTypeGenericArguments[i];
+        var subTypeGenericArgument = subTypeGenericArguments[i];
+
+        if (baseTypeGenericArgument.IsGenericParameter ^ subTypeGenericArgument.IsGenericParameter) return false;
+        if (baseTypeGenericArgument == subTypeGenericArgument) continue;
+        if (!baseTypeGenericArgument.IsGenericParameter && !subTypeGenericArgument.IsGenericParameter) return false;
+
+        if (baseTypeGenericArgument.GenericParameterAttributes.HasFlag(GenericParameterAttributes.ReferenceTypeConstraint) &&
+            !subTypeGenericArgument.GenericParameterAttributes.HasFlag(GenericParameterAttributes.ReferenceTypeConstraint)) return false;
+        if (baseTypeGenericArgument.GenericParameterAttributes.HasFlag(GenericParameterAttributes.DefaultConstructorConstraint) &&
+            !subTypeGenericArgument.GenericParameterAttributes.HasFlag(GenericParameterAttributes.DefaultConstructorConstraint)) return false;
+        if (baseTypeGenericArgument.GenericParameterAttributes.HasFlag(GenericParameterAttributes.NotNullableValueTypeConstraint) &&
+            !subTypeGenericArgument.GenericParameterAttributes.HasFlag(GenericParameterAttributes.NotNullableValueTypeConstraint)) return false;
+
+        foreach (var baseTypeGenericParameterConstraint in baseTypeGenericArgument.GetGenericParameterConstraints()) {
+          if (!subTypeGenericArgument.GetGenericParameterConstraints().Any(t => baseTypeGenericParameterConstraint.IsAssignableFrom(t))) return false;
+        }
+      }
+      return true;
+    }
+  }
+}
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Utils/UniPath.cs
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Utils/UniPath.cs	(revision 16984)
+++ branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Utils/UniPath.cs	(revision 16984)
@@ -0,0 +1,49 @@
+﻿using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace HeuristicLab.PluginInfrastructure {
+  [Serializable]
+  public class UniPath {
+
+    #region Vars
+    private string fullPath = "";
+    #endregion
+
+    #region Constructors
+    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) {
+        tmp += splits[i] + seperator;
+        ++i;
+      }
+      tmp += splits[i];
+      return tmp;
+    }
+
+    public override string ToString() {
+      bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
+      if (isWindows) {
+        if (IsWindowsAbsolutePath(fullPath))
+          return fullPath;
+        else return Rebuild('/', @"C:\", @"\");
+      } else {
+        if (IsWindowsAbsolutePath(fullPath))
+          return Rebuild('\\', "/", "/");
+        else return fullPath;
+      }
+    }
+  }
+}
Index: branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/app.config
===================================================================
--- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/app.config	(revision 16859)
+++ 	(revision )
@@ -1,13 +1,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<configuration>
-  <configSections>
-    <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
-      <section name="HeuristicLab.PluginInfrastructure.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false"/>
-    </sectionGroup>
-  </configSections>
-
-
-  <startup>
-    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
-  </startup>
-</configuration>
