- Timestamp:
- 05/24/19 12:28:29 (6 years ago)
- Location:
- branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3
- Files:
-
- 11 added
- 8 deleted
- 9 edited
- 3 copied
- 3 moved
Legend:
- Unmodified
- Added
- Removed
-
branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/ApplicationBase.cs
r13341 r16984 21 21 22 22 23 using System; 24 23 25 namespace HeuristicLab.PluginInfrastructure { 24 26 /// <summary> 25 27 /// Abstract base implementation for the IApplication interface. 26 28 /// </summary> 29 [Serializable] 27 30 public abstract class ApplicationBase : IApplication { 28 31 /// <summary> … … 69 72 public abstract void Run(ICommandLineArgument[] args); 70 73 74 public virtual void OnCancel() { Console.WriteLine("OnCancellation"); } 75 public virtual void OnPause() { Console.WriteLine("OnPause"); } 76 public virtual void OnResume() { Console.WriteLine("OnResume"); } 77 71 78 #endregion 72 79 } -
branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/ApplicationDescription.cs
r13389 r16984 26 26 /// Class that provides information about an application. 27 27 /// </summary> 28 [Serializable]28 /*[Serializable] 29 29 public sealed class ApplicationDescription : IApplicationDescription { 30 30 private string name; … … 86 86 return Name + " " + Version; 87 87 } 88 } 88 }*/ 89 89 } -
branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/HeuristicLab.PluginInfrastructure-3.3.csproj
r16859 r16984 19 19 <PackageReference Include="System.CodeDom" Version="4.5.0" /> 20 20 <PackageReference Include="System.Drawing.Common" Version="4.5.1" /> 21 <PackageReference Include="System.Runtime.Loader" Version="4.3.0" /> 21 22 <PackageReference Include="System.Security.Cryptography.ProtectedData" Version="4.5.0" /> 22 23 <PackageReference Include="System.ServiceModel.Primitives" Version="4.5.3" /> … … 24 25 <PackageReference Include="System.Security.Cryptography.Primitives" Version="4.3.0" /> 25 26 </ItemGroup> 27 <ItemGroup> 28 <Folder Include="Exceptions\" /> 29 </ItemGroup> 26 30 </Project> -
branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Interfaces/IApplication.cs
r15973 r16984 38 38 /// </summary> 39 39 void Run(ICommandLineArgument[] args); 40 41 /// <summary> 42 /// This method gets called when a cancellation is invoked. 43 /// </summary> 44 void OnCancel(); 45 46 /// <summary> 47 /// This method gets called when a pause is invoked. 48 /// </summary> 49 void OnPause(); 50 51 /// <summary> 52 /// This method gets called when a resume is invoked. 53 /// </summary> 54 void OnResume(); 40 55 } 41 56 } -
branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Interfaces/IApplicationManager.cs
r15973 r16984 52 52 /// <returns>An enumerable of instances of the discovered types.</returns> 53 53 IEnumerable<object> GetInstances(Type type); 54 55 /// <summary> 56 /// Discovers a specific type by its name. 57 /// </summary> 58 /// <param name="typeName">Full name of the type.</param> 59 /// <returns>A type or null, if nothing was found.</returns> 60 Type GetType(string typeName); 54 61 55 62 /// <summary> -
branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Interfaces/IAssemblyLoader.cs
r16859 r16984 2 2 using System.Collections.Generic; 3 3 using System.Reflection; 4 using System.Text;5 4 6 5 namespace HeuristicLab.PluginInfrastructure { 6 /// <summary> 7 /// Interface for an assembly loading mechanism 8 /// </summary> 7 9 public interface IAssemblyLoader { 8 string BasePath { get; set; }9 10 10 /// <summary> 11 11 /// Returns all loaded assemblies. 12 12 /// </summary> 13 13 IEnumerable<Assembly> Assemblies { get; } 14 14 15 /// <summary> 15 16 /// Returns all types. … … 18 19 19 20 /// <summary> 20 /// Returns all assemblies included in BasePath.21 /// Loads all assemblies (.dll/.exe) in the specified path. 21 22 /// </summary> 22 /// <returns></returns> 23 IEnumerable<Assembly> GetReflectionOnlyAssemblies(); 23 /// <param name="basePath">Path to root directory of all assemblies to load.</param> 24 /// <returns>An IEnumerable of assemblies.</returns> 25 IEnumerable<Assembly> LoadAssemblies(string basePath); 24 26 25 27 /// <summary> 26 /// Loads all assembliesm which are given by the assemblyName argument, into the current context.28 /// Loads all specified assemblies. 27 29 /// </summary> 28 /// <param name="assemblyNames"></param> 29 /// <returns>All loaded assemblies.</returns> 30 IEnumerable<Assembly> LoadAssemblies(IEnumerable<AssemblyName> assemblyNames); 31 30 /// <param name="assemblyInfos">Infos for all assemblies to load.</param> 31 /// <returns>An IEnumerable of assemblies.</returns> 32 IEnumerable<Assembly> LoadAssemblies(IEnumerable<AssemblyInfo> assemblyInfos); 32 33 } 33 34 } -
branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Interfaces/IPluginLoader.cs
r16859 r16984 1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 using HeuristicLab.PluginInfrastructure; 1 using System.Collections.Generic; 5 2 6 3 namespace HeuristicLab.PluginInfrastructure { 4 /// <summary> 5 /// Interface for a plugin load mechanism. 6 /// </summary> 7 7 public interface IPluginLoader { 8 /// <summary>9 /// Returns all activators found.10 /// </summary>11 IList<IActivator> Activators { get; }12 13 8 /// <summary> 14 9 /// Returns all plugins found. 15 10 /// </summary> 16 I List<IPlugin> Plugins { get; }11 IEnumerable<IPlugin> Plugins { get; } 17 12 18 13 /// <summary> 19 14 /// Returns all Applications found. 20 15 /// </summary> 21 IList<IApplication> Applications { get; } 16 IEnumerable<IApplication> Applications { get; } 17 18 /// <summary> 19 /// Load plugins, definied by the given AssemblyInfos. 20 /// </summary> 21 /// <param name="assemblyInfos">AssemblyInfos for the assemblies, which should be loaded.</param> 22 void LoadPlugins(IEnumerable<AssemblyInfo> assemblyInfos); 23 24 /// <summary> 25 /// Searches for .dll/.exe files and validates them. 26 /// </summary> 27 /// <param name="basePath">Path of the root directory for the assemblies to validate.</param> 28 /// <returns>A IEnumerable of AssemblyInfos, which contains all loadable assemblies. </returns> 29 IEnumerable<AssemblyInfo> Validate(string basePath); 22 30 } 23 31 } -
branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Interfaces/IRunner.cs
r16859 r16984 1 1 using System; 2 2 using System.Collections.Generic; 3 using System.IO; 3 4 using System.Text; 4 5 5 6 namespace HeuristicLab.PluginInfrastructure { 6 7 /// <summary>8 /// Interface for all runner implementations.9 /// </summary>10 7 public interface IRunner { 11 8 /// <summary> 12 /// Method to start the runner which scans all assemblies in the given basePath argument. 13 /// Additionally, arguments can be specified, which are forwarded to all activators. 9 /// Set this to true, if console output should be disabled. 14 10 /// </summary> 15 /// <param name="basePath"></param> 16 /// <param name="args"></param> 17 void Start(string basePath, string[] args); 11 bool QuietMode { get; set; } 18 12 19 void Stop(); 13 /// <summary> 14 /// Assemblies which the child process needs to load. 15 /// </summary> 16 IEnumerable<AssemblyInfo> AssembliesToLoad { get; set; } 17 18 /// <summary> 19 /// Method to run the runner. 20 /// </summary> 21 void Run(); 20 22 } 21 23 } -
branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/AssemblyLoader.cs
r16983 r16984 1 1 using System; 2 using System.Linq;3 2 using System.Collections.Generic; 4 3 using System.IO; 4 using System.Linq; 5 5 using System.Reflection; 6 6 using System.Runtime.Loader; 7 using System.Runtime.Versioning;8 using System.Threading.Tasks;9 7 10 namespace HeuristicLab.PluginInfrastructure .Runner{8 namespace HeuristicLab.PluginInfrastructure { 11 9 10 /// <summary> 11 /// Class to load assemblies. 12 /// </summary> 12 13 public class AssemblyLoader : IAssemblyLoader { 14 /// <summary> 15 /// Comparer for AssemblyNames. 16 /// </summary> 13 17 private class AssemblyNameComparer : IEqualityComparer<AssemblyName> { 14 18 private object concatProps(AssemblyName name) => name.FullName + name.Version.ToString(); … … 17 21 } 18 22 19 //https://github.com/dotnet/coreclr/blob/master/Documentation/design-docs/assemblyloadcontext.md 20 private class ALC : AssemblyLoadContext { 21 private Dictionary<AssemblyName, Assembly> loadedAssemblies = new Dictionary<AssemblyName, Assembly>(new AssemblyNameComparer()); 22 private string BasePath { get; set; } 23 public ALC(string basePath) { BasePath = basePath; } 24 protected override Assembly Load(AssemblyName assemblyName) { 25 if (loadedAssemblies.ContainsKey(assemblyName)) return loadedAssemblies[assemblyName]; 23 #region Vars 24 private readonly IList<Assembly> assemblies = new List<Assembly>(); 25 private readonly IList<Type> types = new List<Type>(); 26 #endregion 26 27 27 string path = $"{BasePath}{Path.DirectorySeparatorChar}{assemblyName.Name}.dll"; 28 Assembly asm = null; 29 if (File.Exists(path)) 30 asm = Assembly.LoadFrom(path); 31 else 32 asm = Assembly.Load(assemblyName); 33 loadedAssemblies.Add(assemblyName, asm); 34 foreach (var a in asm.GetReferencedAssemblies()) 35 Load(a); 36 return asm; 37 } 38 } 39 40 private ALC alc; 41 public string BasePath { get; set; } 42 public string AssemblyPrefix { get; set; } 43 44 //public IList<Assembly> Assemblies { private set; get; } = new List<Assembly>(); 45 //public IList<Type> Types { private set; get; } = new List<Type>(); 46 47 private IList<Assembly> assemblies = new List<Assembly>(); 28 #region Properties 29 /// <summary> 30 /// All loaded assemblies. Contains items only after a call of LoadAssemblies. 31 /// </summary> 48 32 public IEnumerable<Assembly> Assemblies => assemblies; 49 33 50 private IList<Type> types = new List<Type>(); 34 /// <summary> 35 /// All types found in all assemblies. 36 /// </summary> 51 37 public IEnumerable<Type> Types => types; 38 #endregion 52 39 53 public AssemblyLoader() : this(Directory.GetCurrentDirectory()) { }54 public AssemblyLoader( string basePath) {55 this.BasePath = basePath; 56 alc = new ALC(BasePath);40 #region Constructors 41 public AssemblyLoader() { 42 43 #region alternative code 57 44 /* 58 45 ScanTypesInBasePath(); … … 67 54 //LoadAssemblies(asms); 68 55 //LoadTypes(asms); 56 #endregion 57 } 58 #endregion 59 60 61 private IEnumerable<string> GetAssembliesFromBasePath(string basePath) { 62 return Directory.GetFiles(basePath, "*.dll", SearchOption.AllDirectories) 63 .Concat(Directory.GetFiles(basePath, "*.exe", SearchOption.AllDirectories)); 69 64 } 70 65 71 // 1. 72 private IEnumerable<string> GetAssembliesFromBasePath() { 73 return Directory.GetFiles(BasePath, $"*.dll", SearchOption.AllDirectories); 74 } 66 #region alternative code 75 67 /* 76 68 // 2. … … 126 118 } 127 119 */ 120 #endregion 121 122 128 123 private void LoadTypes(IEnumerable<Assembly> assemblies) { 129 124 foreach (Assembly asm in assemblies) { … … 133 128 } 134 129 } catch (ReflectionTypeLoadException e) { 130 // ReflectionTypeLoadException gets thrown if any class in a module cannot be loaded. 135 131 try { 136 foreach (Type t in e.Types) { 132 foreach (Type t in e.Types) { // fetch the already loaded types, be careful some of them can be null 137 133 if (t != null) { 138 134 types.Add(t); … … 140 136 } 141 137 } catch (BadImageFormatException) { } 142 143 } catch (Exception e) { 144 Tracing.Logger.Error( 145 $"Exception occured while loading types of assembly {asm.FullName}! \n " + 146 $"---- Stacktrace ---- \n {e}"); 138 } catch (Exception e) { // to catch every other exception 139 //Tracing.Logger.Error( 140 // $"Exception occured while loading types of assembly {asm.FullName}! \n " + 141 // $"---- Stacktrace ---- \n {e}"); 147 142 } 148 143 } 149 144 } 150 /*151 public Type GetType(string type) {152 foreach (Assembly asm in Assemblies) {153 Type t = asm.GetType(type);154 if (t != null) return t;155 }156 return null;157 }158 */159 145 160 public IEnumerable<Assembly> GetReflectionOnlyAssemblies() { 161 IList<Assembly> list = new List<Assembly>(); 162 foreach (string path in GetAssembliesFromBasePath()) { 163 try { 164 var asm = Assembly.LoadFrom(path); 165 if (asm != null) 166 list.Add(asm); 167 else 168 Tracing.Logger.Error($"Unnable to load assembly with path {path}!"); 169 } catch (Exception e) { 170 Tracing.Logger.Error( 171 $"Exception occured while loading assembly from path {path}! \n " + 172 $"---- Stacktrace ---- \n {e}"); 173 } 174 } 175 return list; 176 } 177 178 public IEnumerable<Assembly> LoadAssemblies(IEnumerable<AssemblyName> assemblyNames) { 179 foreach (AssemblyName asm in assemblyNames) { 180 try { 181 this.assemblies.Add(alc.LoadFromAssemblyName(asm)); 182 } catch (Exception e) { 183 Tracing.Logger.Error( 184 $"Exception occured while loading assembly: {asm.FullName}! \n " + 185 $"---- Stacktrace ---- \n {e}"); 186 } 187 } 146 public IEnumerable<Assembly> LoadAssemblies(string basePath) { 147 foreach (string path in GetAssembliesFromBasePath(basePath)) 148 LoadAssemblyFromPath(path); 149 188 150 LoadTypes(this.Assemblies); 189 151 return this.Assemblies; 190 152 } 153 154 public IEnumerable<Assembly> LoadAssemblies(IEnumerable<AssemblyInfo> assemblyInfos) { 155 foreach (var info in assemblyInfos) 156 LoadAssemblyFromPath(info.Path.ToString()); 157 158 LoadTypes(this.Assemblies); 159 return this.Assemblies; 160 } 161 162 private void LoadAssemblyFromPath(string path) { 163 try { 164 var asm = AssemblyLoadContext.Default.LoadFromAssemblyPath(path); // loads assembly into default context 165 if (asm != null) { 166 assemblies.Add(asm); 167 } // else 168 //Tracing.Logger.Error($"Unnable to load assembly with path {path}!"); 169 } catch (Exception e) { // to catch every exception occured by assembly loading. 170 //Tracing.Logger.Error( 171 // $"Exception occured while loading assembly from path {path}! \n " + 172 // $"---- Stacktrace ---- \n {e}"); 173 } 174 } 191 175 } 192 176 } -
branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/PluginLoader.cs
r16983 r16984 1 1 using System; 2 using System.Collections.Generic; 3 using System.IO; 2 4 using System.Linq; 3 using System.Collections.Generic; 5 using System.Reflection; 6 using System.Security; 4 7 using System.Text; 5 using HeuristicLab.PluginInfrastructure; 6 using System.Reflection; 7 using System.IO; 8 using System.Security; 9 10 namespace HeuristicLab.PluginInfrastructure.Runner { 11 internal class PluginLoader : IPluginLoader { 12 8 9 namespace HeuristicLab.PluginInfrastructure { 10 public class PluginLoader : IPluginLoader { 11 12 /// <summary> 13 /// Helper class for depedency metadata. 14 /// </summary> 13 15 private class PluginDependency { 14 16 public string Name { get; private set; } 15 17 public Version Version { get; private set; } 16 17 18 public PluginDependency(string name, Version version) { 18 19 this.Name = name; … … 21 22 } 22 23 23 private IList<IPlugin> plugins = null; 24 public IList<IPlugin> Plugins { 25 private set => plugins = value; 26 get { 27 if (plugins == null) { 28 Plugins = new List<IPlugin>(); 29 DiscoverPlugins(); 30 } 31 return plugins; 32 } 33 } 34 35 private IList<IApplication> applications = null; 36 public IList<IApplication> Applications { 37 private set => applications = value; 38 get { 39 if (applications == null) { 40 Applications = new List<IApplication>(); 41 DiscoverApplications(); 42 } 43 return applications; 44 } 45 } 46 47 private IList<IActivator> activators = null; 48 public IList<IActivator> Activators { 49 private set => activators = value; 50 get { 51 if (activators == null) { 52 activators = new List<IActivator>(); 53 DiscoverActivators(); 54 } 55 return activators; 56 } 57 } 58 59 60 #region oldCode 24 #region Vars 25 private IList<IPlugin> plugins = new List<IPlugin>(); 26 private IList<IApplication> applications = new List<IApplication>(); 27 private IAssemblyLoader assemblyLoader = null; 61 28 private Dictionary<PluginDescription, IEnumerable<PluginDependency>> pluginDependencies = new Dictionary<PluginDescription, IEnumerable<PluginDependency>>(); 62 29 #endregion 63 private IEnumerable<Assembly> reflectionOnlyAssemblies; 64 private IAssemblyLoader asmLoader; 65 private string BasePath { get; set; } 66 67 public PluginLoader(string basePath, IAssemblyLoader assemblyLoader) { 68 asmLoader = assemblyLoader; 69 this.BasePath = basePath; 70 Init(); 71 } 72 73 private void Init() { 74 reflectionOnlyAssemblies = asmLoader.GetReflectionOnlyAssemblies(); 75 76 IEnumerable<PluginDescription> pluginDescriptions = GatherPluginDescriptions(reflectionOnlyAssemblies); 77 78 79 CheckPluginFiles(pluginDescriptions); 30 31 #region Properties 32 public IEnumerable<IPlugin> Plugins => plugins; 33 34 public IEnumerable<IApplication> Applications => applications; 35 #endregion 36 37 #region Constructors 38 public PluginLoader(IAssemblyLoader assemblyLoader) { 39 this.assemblyLoader = assemblyLoader; 40 } 41 #endregion 42 43 #region Discover Methods 44 public void LoadPlugins(IEnumerable<AssemblyInfo> assemblyInfos) { 45 assemblyLoader.LoadAssemblies(assemblyInfos); 46 DiscoverPlugins(); 47 DiscoverApplications(); 48 } 49 /// <summary> 50 /// Discovers all types of IPlugin of all loaded assemblies. Saves the found plugins in a list. 51 /// </summary> 52 private void DiscoverPlugins() { 53 // search plugins out of all types 54 string curDir = Directory.GetCurrentDirectory(); // save current working directory 55 foreach (var type in assemblyLoader.Types) { 56 if (typeof(IPlugin).IsAssignableFrom(type) && !type.IsAbstract && !type.IsInterface && !type.HasElementType) { 57 // to set the working directory to the assembly location, this is necessary for assemblies which load data in the OnLoad method by their own. 58 // example: HeuristicLabMathJaxPlugin 59 Directory.SetCurrentDirectory(type.Assembly.Location.Replace(Path.GetFileName(type.Assembly.Location), "")); 60 IPlugin p = (IPlugin)Activator.CreateInstance(type); 61 p.OnLoad(); 62 plugins.Add(p); 63 } 64 } 65 Directory.SetCurrentDirectory(curDir); // set working directory to its base value 66 } 67 68 /// <summary> 69 /// Discovers all types of IApplication of all loaded assemblies. Saves the found applications in a list. 70 /// </summary> 71 private void DiscoverApplications() { 72 foreach (Type type in assemblyLoader.Types) { 73 if (typeof(IApplication).IsAssignableFrom(type) && !type.IsAbstract && !type.IsInterface && !type.HasElementType) { 74 IApplication app = (IApplication)Activator.CreateInstance(type); 75 applications.Add(app); 76 } 77 } 78 } 79 #endregion 80 81 public IEnumerable<AssemblyInfo> Validate(string basePath) { 82 IEnumerable<Assembly> assemblies = assemblyLoader.LoadAssemblies(basePath); 83 84 IList<PluginDescription> pluginDescriptions = GatherPluginDescriptions(assemblies, basePath); 85 CheckPluginFiles(pluginDescriptions, basePath); 80 86 81 87 // check if all plugin assemblies can be loaded 82 CheckPluginAssemblies( pluginDescriptions);88 CheckPluginAssemblies(assemblies, pluginDescriptions); 83 89 84 90 // a full list of plugin descriptions is available now we can build the dependency tree … … 93 99 // in the next step 94 100 CheckPluginDependencies(pluginDescriptions); 95 // load assemblies 96 IEnumerable<Assembly> assemblies = asmLoader.LoadAssemblies( 97 pluginDescriptions 98 .Where(x => x.PluginState != PluginState.Disabled) 99 .SelectMany( 100 x => x.AssemblyLocations 101 .SelectMany(loc => 102 reflectionOnlyAssemblies 103 .Where(asm => string.Equals(Path.GetFullPath(asm.Location), Path.GetFullPath(loc), StringComparison.CurrentCultureIgnoreCase)) 104 .Select(asm => asm.GetName()) 105 ) 106 ) 107 ); 108 } 109 110 private void DiscoverPlugins() { 111 // search plugins out of all types 112 foreach (var type in asmLoader.Types) { 113 if (typeof(IPlugin).IsAssignableFrom(type) && !type.IsAbstract && !type.IsInterface && !type.HasElementType) { 114 IPlugin p = (IPlugin)Activator.CreateInstance(type); 115 //p.OnLoad(); 116 Plugins.Add(p); 117 } 118 } 119 120 #region oldCode 121 /* 122 IEnumerable<PluginDescription> pluginDescriptions = GatherPluginDescriptions(asmLoader.Assemblies); 123 124 CheckPluginFiles(pluginDescriptions); 125 //--> checken ob alle assemblies physisch vorliegen die benötigt werden (depedency) 126 127 // check if all plugin assemblies can be loaded 128 CheckPluginAssemblies(pluginDescriptions); //--> ob sie auch geladen werden können 129 //--> 1. und 2. könnte man zusammenfassen, da eh schon assemblies gescannt und geladen wurden ... checken ob diese vorliegen -> asmLoader.Assemblies 130 131 // a full list of plugin descriptions is available now we can build the dependency tree 132 BuildDependencyTree(pluginDescriptions); //--> gleich auf assembly basis?! 133 134 // check for dependency cycles 135 CheckPluginDependencyCycles(pluginDescriptions); 136 137 // 1st time recursively check if all necessary plugins are available and not disabled 138 // disable plugins with missing or disabled dependencies 139 // to prevent that plugins with missing dependencies are loaded into the execution context 140 // in the next step 141 CheckPluginDependencies(pluginDescriptions); //--> "disabled" assemblies merken (evtl. mit Dictionary) 142 143 // test full loading (in contrast to reflection only loading) of plugins 144 // disables plugins that are not loaded correctly 145 CheckExecutionContextLoad(pluginDescriptions); 146 147 // 2nd time recursively check if all necessary plugins have been loaded successfully and not disabled 148 // disable plugins with for which dependencies could not be loaded successfully 149 CheckPluginDependencies(pluginDescriptions); 150 151 foreach (var desc in pluginDescriptions) 152 if (desc.PluginState != PluginState.Disabled) 153 desc.Enable(); 154 155 // load the enabled plugins 156 LoadPlugins(pluginDescriptions); 157 */ 158 #endregion 159 } 160 161 private void DiscoverApplications() { 162 foreach (Type type in asmLoader.Types) { 163 if (typeof(IApplication).IsAssignableFrom(type) && !type.IsAbstract && !type.IsInterface && !type.HasElementType) { 164 IApplication app = (IApplication)Activator.CreateInstance(type); 165 Applications.Add(app); 166 } 167 } 168 } 169 170 private void DiscoverActivators() { 171 foreach (Type type in asmLoader.Types) { 172 if (typeof(IActivator).IsAssignableFrom(type) && !type.IsAbstract && !type.IsInterface && !type.HasElementType) { 173 IActivator act = (IActivator)Activator.CreateInstance(type); 174 Activators.Add(act); 175 } 176 } 101 102 // build assemblyInfo list: 103 // 1.) iterate through pluginDescriptions and pick all not disabled plugins 104 // 2.) iterate through the assemblyLocations, saved in a description 105 // 3.) iterate thorugh all loaded assemblies 106 // 4.) if the location of an assemblies and a pluginDescriptions match -> create new AssemblyInfo and add it to a list 107 IList<AssemblyInfo> list = new List<AssemblyInfo>(); 108 foreach (var desc in pluginDescriptions) { 109 if (desc.PluginState != PluginState.Disabled) { 110 foreach (var loc in desc.AssemblyLocations) { 111 foreach (var asm in assemblies) { 112 if (string.Equals(Path.GetFullPath(asm.Location), Path.GetFullPath(loc), StringComparison.CurrentCultureIgnoreCase)) 113 list.Add(new AssemblyInfo() { Path = new UniPath(asm.Location), Name = asm.FullName }); 114 } 115 } 116 } 117 } 118 119 return list; 177 120 } 178 121 … … 182 125 /// </summary> 183 126 /// <param name="pluginDescriptions"></param> 184 private void CheckPluginAssemblies(IEnumerable< PluginDescription> pluginDescriptions) {127 private void CheckPluginAssemblies(IEnumerable<Assembly> assemblies, IEnumerable<PluginDescription> pluginDescriptions) { 185 128 foreach (var desc in pluginDescriptions.Where(x => x.PluginState != PluginState.Disabled)) { 186 129 try { … … 190 133 // so we simply determine the name of the assembly and try to find it in the cache of loaded assemblies 191 134 var asmName = AssemblyName.GetAssemblyName(asmLocation); 192 if (! reflectionOnlyAssemblies.Select(x => x.GetName().FullName).Contains(asmName.FullName)) {135 if (!assemblies.Select(x => x.GetName().FullName).Contains(asmName.FullName)) { 193 136 missingAssemblies.Add(asmName.FullName); 194 137 } … … 225 168 // the dependencies in the plugin descriptions are not yet set correctly because we need to create 226 169 // the full list of all plugin descriptions first 227 private I Enumerable<PluginDescription> GatherPluginDescriptions(IEnumerable<Assembly> assemblies) {170 private IList<PluginDescription> GatherPluginDescriptions(IEnumerable<Assembly> assemblies, string basePath) { 228 171 List<PluginDescription> pluginDescriptions = new List<PluginDescription>(); 229 172 foreach (Assembly assembly in assemblies) { … … 234 177 // use AssemblyQualifiedName to compare the types because we can't directly 235 178 // compare ReflectionOnly types and execution types 179 236 180 var assemblyPluginDescriptions = from t in assembly.GetExportedTypes() 237 181 where !t.IsAbstract && t.GetInterfaces() 238 182 .Any(x => x.AssemblyQualifiedName == typeof(IPlugin).AssemblyQualifiedName) 239 select GetPluginDescription(t );183 select GetPluginDescription(t, basePath); 240 184 pluginDescriptions.AddRange(assemblyPluginDescriptions); 241 185 } … … 252 196 253 197 // checks if all declared plugin files are actually available and disables plugins with missing files 254 private void CheckPluginFiles(IEnumerable<PluginDescription> pluginDescriptions ) {198 private void CheckPluginFiles(IEnumerable<PluginDescription> pluginDescriptions, string basePath) { 255 199 foreach (PluginDescription desc in pluginDescriptions) { 256 200 IEnumerable<string> missingFiles; 257 if (ArePluginFilesMissing(desc, out missingFiles)) {201 if (ArePluginFilesMissing(desc, basePath, out missingFiles)) { 258 202 StringBuilder errorStrBuilder = new StringBuilder(); 259 203 errorStrBuilder.AppendLine("Missing files:"); … … 266 210 } 267 211 268 private bool ArePluginFilesMissing(PluginDescription pluginDescription, out IEnumerable<string> missingFiles) {212 private bool ArePluginFilesMissing(PluginDescription pluginDescription, string basePath, out IEnumerable<string> missingFiles) { 269 213 List<string> missing = new List<string>(); 270 214 foreach (string filename in pluginDescription.Files.Select(x => x.Name)) { 271 if (!FileLiesInDirectory( BasePath, filename) ||215 if (!FileLiesInDirectory(basePath, filename) || 272 216 !File.Exists(filename)) { 273 217 missing.Add(filename); … … 289 233 /// </summary> 290 234 /// <param name="pluginType"></param> 291 private PluginDescription GetPluginDescription(Type pluginType ) {235 private PluginDescription GetPluginDescription(Type pluginType, string basePath) { 292 236 293 237 string pluginName, pluginDescription, pluginVersion; … … 295 239 GetPluginMetaData(pluginType, out pluginName, out pluginDescription, out pluginVersion); 296 240 GetPluginContactMetaData(pluginType, out contactName, out contactAddress); 297 var pluginFiles = GetPluginFilesMetaData(pluginType );241 var pluginFiles = GetPluginFilesMetaData(pluginType, basePath); 298 242 var pluginDependencies = GetPluginDependencyMetaData(pluginType); 299 243 … … 373 317 374 318 // not static because we need the BasePath property 375 private IEnumerable<PluginFile> GetPluginFilesMetaData(Type pluginType ) {319 private IEnumerable<PluginFile> GetPluginFilesMetaData(Type pluginType, string basePath) { 376 320 // get all attributes of type PluginFileAttribute 377 321 var pluginFileAttributes = from attr in CustomAttributeData.GetCustomAttributes(pluginType) … … 381 325 string pluginFileName = (string)pluginFileAttribute.ConstructorArguments[0].Value; 382 326 PluginFileType fileType = (PluginFileType)pluginFileAttribute.ConstructorArguments[1].Value; 383 yield return new PluginFile(Path.GetFullPath(Path.Combine( BasePath, pluginFileName)), fileType);327 yield return new PluginFile(Path.GetFullPath(Path.Combine(basePath, pluginFileName)), fileType); 384 328 } 385 329 } … … 405 349 } 406 350 } 351 407 352 408 353 private static bool IsAttributeDataForType(CustomAttributeData attributeData, Type attributeType) { … … 496 441 } 497 442 498 499 443 private bool IsAnyDependencyDisabled(PluginDescription descr, List<PluginDescription> disabledPlugins) { 500 444 if (descr.PluginState == PluginState.Disabled) { … … 507 451 return disabledPlugins.Count > 0; 508 452 } 509 510 // tries to load all plugin assemblies into the execution context511 // if an assembly of a plugin cannot be loaded the plugin is disabled512 private void CheckExecutionContextLoad(IEnumerable<PluginDescription> pluginDescriptions) {513 // load all loadable plugins (all dependencies available) into the execution context514 foreach (var desc in PluginDescriptionIterator.IterateDependenciesBottomUp(pluginDescriptions515 .Where(x => x.PluginState != PluginState.Disabled))) {516 // store the assembly names so that we can later retrieve the assemblies loaded in the appdomain by name517 var assemblyNames = new List<string>();518 foreach (string assemblyLocation in desc.AssemblyLocations) {519 if (desc.PluginState != PluginState.Disabled) {520 try {521 string assemblyName = (from assembly in asmLoader.Assemblies//AppDomain.CurrentDomain.ReflectionOnlyGetAssemblies()522 where string.Equals(Path.GetFullPath(assembly.Location), Path.GetFullPath(assemblyLocation), StringComparison.CurrentCultureIgnoreCase)523 select assembly.FullName).Single();524 // now load the assemblies into the execution context525 // this can still lead to an exception526 // even when the assemby was successfully loaded into the reflection only context before527 // when loading the assembly using it's assemblyName it can be loaded from a different location than before (e.g. the GAC)528 //Assembly.Load(assemblyName);529 assemblyNames.Add(assemblyName);530 } catch (BadImageFormatException) {531 desc.Disable(Path.GetFileName(assemblyLocation) + " is not a valid assembly.");532 } catch (FileLoadException) {533 desc.Disable("Can't load file " + Path.GetFileName(assemblyLocation));534 } catch (FileNotFoundException) {535 desc.Disable("File " + Path.GetFileName(assemblyLocation) + " is missing.");536 } catch (SecurityException) {537 desc.Disable("File " + Path.GetFileName(assemblyLocation) + " can't be loaded because of security constraints.");538 } catch (NotSupportedException ex) {539 // disable the plugin540 desc.Disable("Problem while loading plugin assemblies:" + Environment.NewLine + "NotSupportedException: " + ex.Message);541 }542 }543 }544 desc.AssemblyNames = assemblyNames;545 }546 }547 548 // assumes that all plugin assemblies have been loaded into the execution context via CheckExecutionContextLoad549 // for each enabled plugin:550 // calls OnLoad method of the plugin551 // and raises the PluginLoaded event552 private void LoadPlugins(IEnumerable<PluginDescription> pluginDescriptions) {553 List<Assembly> assemblies = new List<Assembly>(asmLoader.Assemblies);554 plugins = new List<IPlugin>();555 foreach (var desc in pluginDescriptions) {556 if (desc.PluginState == PluginState.Enabled) {557 // cannot use ApplicationManager to retrieve types because it is not yet instantiated558 foreach (string assemblyName in desc.AssemblyNames) {559 var asm = (from assembly in assemblies560 where assembly.FullName == assemblyName561 select assembly)562 .SingleOrDefault();563 if (asm == null) throw new InvalidPluginException("Could not load assembly " + assemblyName + " for plugin " + desc.Name);564 foreach (Type pluginType in asm.GetExportedTypes()) {565 if (typeof(IPlugin).IsAssignableFrom(pluginType) && !pluginType.IsAbstract && !pluginType.IsInterface && !pluginType.HasElementType) {566 IPlugin plugin = (IPlugin)Activator.CreateInstance(pluginType);567 plugin.OnLoad();568 plugins.Add(plugin);569 //OnPluginLoaded(new PluginInfrastructureEventArgs(desc));570 }571 }572 } // end foreach assembly in plugin573 desc.Load();574 }575 } // end foreach plugin description576 }577 453 } 578 454 #endregion -
branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/PluginLoaderFactory.cs
r16983 r16984 4 4 using System.Text; 5 5 6 namespace HeuristicLab.PluginInfrastructure.Runner { 7 public class PluginLoaderFactory { 6 namespace HeuristicLab.PluginInfrastructure { 7 /// <summary> 8 /// Factory to create an instance of a plugin loader. 9 /// </summary> 10 public static class PluginLoaderFactory { 11 /// <summary> 12 /// Creates a new instance of a plugin loader. 13 /// </summary> 8 14 public static IPluginLoader Create() { 9 return Create(Directory.GetCurrentDirectory()); 10 } 11 12 internal static IPluginLoader Create(string basePath) { 13 return new PluginLoader(basePath, new AssemblyLoader(basePath)); 15 return new PluginLoader(new AssemblyLoader()); 14 16 } 15 17 } -
branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/LightweightApplicationManager.cs
r15973 r16984 75 75 foreach (Type t in GetTypes(type)) { 76 76 object instance = null; 77 try { instance = Activator.CreateInstance(t); } 78 catch { } 77 try { instance = Activator.CreateInstance(t); } catch { } 79 78 if (instance != null) instances.Add(instance); 80 79 } 81 80 return instances; 81 } 82 83 public Type GetType(string typeName) { 84 foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) { 85 Type t = asm.GetType(typeName); 86 if (t != null) return t; 87 } 88 return null; 82 89 } 83 90 … … 126 133 // necessary to make sure the exception is immediately thrown 127 134 // instead of later when the enumerable is iterated? 135 128 136 var assemblyTypes = assembly.GetTypes(); 129 137 … … 138 146 139 147 return matchingTypes; 140 } 141 catch (TypeLoadException) { 148 } catch (TypeLoadException) { 142 149 return Enumerable.Empty<Type>(); 143 } 144 catch (ReflectionTypeLoadException) { 150 } catch (ReflectionTypeLoadException) { 145 151 return Enumerable.Empty<Type>(); 146 152 }
Note: See TracChangeset
for help on using the changeset viewer.