Changeset 2488 for branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure.Manager
- Timestamp:
- 11/12/09 17:45:45 (15 years ago)
- Location:
- branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure.Manager
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure.Manager/ApplicationDescription.cs
r2481 r2488 29 29 /// </summary> 30 30 [Serializable] 31 public class ApplicationDescription {31 public class ApplicationDescription : IApplicationDescription { 32 32 private string name; 33 33 … … 67 67 } 68 68 69 private string pluginAssembly;69 private string declaringAssemblyName; 70 70 /// <summary> 71 71 /// Gets or sets the name of the assembly that contains the IApplication type. 72 72 /// </summary> 73 public string PluginAssembly{74 get { return pluginAssembly; }75 set { pluginAssembly= value; }73 public string DeclaringAssemblyName { 74 get { return declaringAssemblyName; } 75 set { declaringAssemblyName = value; } 76 76 } 77 77 78 private string pluginType;78 private string declaringTypeName; 79 79 /// <summary> 80 80 /// Gets or sets the name of the type that implements the interface IApplication. 81 81 /// </summary> 82 public string PluginType {83 get { return pluginType; }84 set { pluginType = value; }82 public string DeclaringTypeName { 83 get { return declaringTypeName; } 84 set { declaringTypeName = value; } 85 85 } 86 86 } -
branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure.Manager/ApplicationManager.cs
r2481 r2488 27 27 using System.Security.Permissions; 28 28 using System.Security; 29 using System.Linq; 29 30 30 31 namespace HeuristicLab.PluginInfrastructure.Manager { 31 32 32 public class ApplicationManager { 33 public class ApplicationManager : MarshalByRefObject, IApplicationManager { 34 private List<IPluginDescription> plugins; 33 35 /// <summary> 34 /// Event handler for actions in the application manager.36 /// Gets all plugins. 35 37 /// </summary> 36 public event PluginManagerActionEventHandler Action; 37 38 // singleton pattern 39 public ApplicationManager() { 40 applications = new List<ApplicationDescription>(); 38 public IEnumerable<IPluginDescription> Plugins { 39 get { return plugins; } 41 40 } 42 41 43 private ApplicationManager singleton = new ApplicationManager(); 44 public ApplicationManager Manager { 45 get { return singleton; } 42 private List<IApplicationDescription> applications; 43 /// <summary> 44 /// Gets all installed applications. 45 /// </summary> 46 public IEnumerable<IApplicationDescription> Applications { 47 get { return applications; } 48 } 49 50 public ApplicationManager() : base() { } 51 52 internal void PrepareApplicationDomain(IEnumerable<IApplicationDescription> apps, IEnumerable<IPluginDescription> plugins) { 53 this.plugins = new List<IPluginDescription>(plugins); 54 this.applications = new List<IApplicationDescription>(apps); 55 PluginInfrastructure.ApplicationManager.RegisterApplicationManager(this); 56 LoadPlugins(plugins); 57 } 58 59 private void LoadPlugins(IEnumerable<IPluginDescription> plugins) { 60 // load all loadable plugins (all dependencies available) into the execution context 61 foreach (var desc in PluginDescriptionIterator.IterateInDependencyOrder(plugins.Where(x => x.PluginState != PluginState.Disabled))) { 62 foreach (var plugin in GetInstances<IPlugin>(desc)) { 63 plugin.OnLoad(); 64 } 65 desc.Load(); 66 } 67 } 68 69 internal void Run(IApplicationDescription appInfo) { 70 IApplication runnablePlugin = (IApplication)Activator.CreateInstance(appInfo.DeclaringAssemblyName, appInfo.DeclaringTypeName).Unwrap(); 71 try { 72 runnablePlugin.Run(); 73 } 74 catch (Exception e) { 75 throw new Exception(String.Format( 76 "Unexpected exception caught: \"{0}\"\r\n" + 77 "Type: {1}\r\n" + 78 "Plugin {2}:\r\n{3}", 79 e.Message, 80 e.GetType().FullName, 81 appInfo.Name, 82 e.ToString())); 83 } 84 } 85 86 /// <summary> 87 /// Creates an instance of all types that are subtypes or the same type of the specified type and declared in <paramref name="plugin"/> 88 /// </summary> 89 /// <typeparam name="T">Most general type.</typeparam> 90 /// <returns>Enumerable of the created instances.</returns> 91 public IEnumerable<T> GetInstances<T>(IPluginDescription plugin) where T : class { 92 return from t in GetTypes(typeof(T), plugin) 93 where !t.IsAbstract && !t.IsInterface && !t.HasElementType 94 select (T)Activator.CreateInstance(t); 95 } 96 /// <summary> 97 /// Creates an instance of all types that are subtypes or the same type of the specified type 98 /// </summary> 99 /// <typeparam name="T">Most general type.</typeparam> 100 /// <returns>Enumerable of the created instances.</returns> 101 public IEnumerable<T> GetInstances<T>() where T : class { 102 return from i in GetInstances(typeof(T)) 103 select (T)i; 104 } 105 106 /// <summary> 107 /// Creates an instance of all types that are subtypes or the same type of the specified type 108 /// </summary> 109 /// <typeparam name="type">Most general type.</typeparam> 110 /// <returns>Enumerable of the created instances.</returns> 111 public IEnumerable<object> GetInstances(Type type) { 112 return from t in GetTypes(type) 113 where !t.IsAbstract && !t.IsInterface && !t.HasElementType 114 select Activator.CreateInstance(t); 115 } 116 117 /// <summary> 118 /// Finds all types that are subtypes or equal to the specified type. 119 /// </summary> 120 /// <param name="type">Most general type for which to find matching types.</param> 121 /// <returns>Enumerable of the discovered types.</returns> 122 public IEnumerable<Type> GetTypes(Type type) { 123 return from asm in AppDomain.CurrentDomain.GetAssemblies() 124 from t in GetTypes(type, asm) 125 select t; 126 } 127 128 /// <summary> 129 /// Finds all types that are subtypes or equal to the specified type if they are part of the given 130 /// <paramref name="plugin"/>. 131 /// </summary> 132 /// <param name="type">Most general type for which to find matching types.</param> 133 /// <param name="plugin">The plugin the subtypes must be part of.</param> 134 /// <returns>Enumerable of the discovered types.</returns> 135 public IEnumerable<Type> GetTypes(Type type, IPluginDescription pluginDescription) { 136 return from asm in AppDomain.CurrentDomain.GetAssemblies() 137 where pluginDescription.Assemblies.Contains(asm.Location) 138 from t in GetTypes(type, asm) 139 select t; 140 } 141 142 /// <summary> 143 /// Gets types that are assignable (same of subtype) to the specified type only from the given assembly. 144 /// </summary> 145 /// <param name="type">Most general type we want to find.</param> 146 /// <param name="assembly">Assembly that should be searched for types.</param> 147 /// <returns>Enumerable of the discovered types.</returns> 148 private IEnumerable<Type> GetTypes(Type type, Assembly assembly) { 149 return from t in assembly.GetTypes() 150 where type.IsAssignableFrom(t) 151 select t; 46 152 } 47 153 48 154 49 private void NotifyListeners(string action, string text) { 50 if (Action != null) { 51 Action(this, new PluginManagerActionEventArgs(text, action)); 52 } 155 // infinite lease time 156 /// <summary> 157 /// Initializes the life time service with infinite lease time. 158 /// </summary> 159 /// <returns><c>null</c>.</returns> 160 public override object InitializeLifetimeService() { 161 return null; 53 162 } 54 163 } 55 164 } 165 -
branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure.Manager/HeuristicLab.PluginInfrastructure.Manager.csproj
r2481 r2488 49 49 <ItemGroup> 50 50 <Compile Include="ApplicationDescription.cs" /> 51 <Compile Include="PluginDescriptionIterator.cs" /> 51 <Compile Include="ApplicationManager.cs"> 52 <SubType>Code</SubType> 53 </Compile> 52 54 <Compile Include="Loader.cs" /> 53 <Compile Include="PluginState.cs" />54 55 <Compile Include="PluginDescription.cs" /> 55 56 <Compile Include="PluginManager.cs" /> 56 57 <Compile Include="PluginManagerActionEventArgs.cs" /> 57 58 <Compile Include="Properties\AssemblyInfo.cs" /> 58 <Compile Include="Runner.cs" />59 59 </ItemGroup> 60 60 <ItemGroup> -
branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure.Manager/Loader.cs
r2481 r2488 55 55 this.plugins = new List<PluginDescription>(); 56 56 this.pluginDependencies = new Dictionary<PluginDescription, List<string>>(); 57 58 AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += ReflectionOnlyAssemblyResolveEventHandler; 59 } 60 61 private Assembly ReflectionOnlyAssemblyResolveEventHandler(object sender, ResolveEventArgs args) { 62 //try { 63 return Assembly.ReflectionOnlyLoad(args.Name); 64 //} 65 //catch (FileLoadException ex) { 66 // return null; 67 //} 57 68 } 58 69 … … 70 81 /// </summary> 71 82 internal void Init() { 72 //AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += delegate(object sender, ResolveEventArgs args) {73 // try {74 // return Assembly.ReflectionOnlyLoad(args.Name);75 // }76 // catch (FileLoadException ex) {77 // return null;78 // }79 //};80 83 pluginDependencies.Clear(); 81 84 … … 91 94 CheckPluginDependencies(pluginDescriptions); 92 95 96 // mark all plugins as enabled that were not disabled in CheckPluginFiles or CheckPluginDependencies 97 foreach (var desc in pluginDescriptions) 98 if (desc.PluginState != PluginState.Disabled) 99 desc.Enable(); 100 93 101 // test full loading (in contrast to reflection only loading) of plugins 94 102 // disables plugins that are not loaded correctly … … 100 108 101 109 private void DiscoverApplications() { 102 DiscoveryService service = new DiscoveryService();103 IApplication[] apps = service.GetInstances<IApplication>();104 110 applications = new List<ApplicationDescription>(); 105 111 106 foreach (IApplication application in apps) {112 foreach (IApplication application in GetApplications()) { 107 113 ApplicationDescription info = new ApplicationDescription(); 108 114 info.Name = application.Name; … … 110 116 info.Description = application.Description; 111 117 info.AutoRestart = application.RestartOnErrors; 112 info. PluginAssembly= application.GetType().Assembly.GetName().Name;113 info. PluginType = application.GetType().Namespace + "." + application.GetType().Name;118 info.DeclaringAssemblyName = application.GetType().Assembly.GetName().Name; 119 info.DeclaringTypeName = application.GetType().Namespace + "." + application.GetType().Name; 114 120 115 121 applications.Add(info); 116 122 } 123 } 124 125 private IEnumerable<IApplication> GetApplications() { 126 return from asm in AppDomain.CurrentDomain.GetAssemblies() 127 from t in asm.GetTypes() 128 where typeof(IApplication).IsAssignableFrom(t) && 129 !t.IsAbstract && !t.IsInterface && !t.HasElementType 130 select (IApplication)Activator.CreateInstance(t); 117 131 } 118 132 … … 198 212 // iterate through all custom attributes and search for attributed that we are interested in 199 213 foreach (CustomAttributeData attributeData in attributes) { 200 if (IsAttributeDataForType(attributeData, typeof(Plugin DescriptionAttribute))) {214 if (IsAttributeDataForType(attributeData, typeof(PluginAttribute))) { 201 215 pluginName = (string)attributeData.ConstructorArguments[0].Value; 202 216 } else if (IsAttributeDataForType(attributeData, typeof(PluginDependencyAttribute))) { … … 222 236 info.AddAssemblies(pluginAssemblies); 223 237 info.AddFiles(pluginFiles); 224 info.PluginState = PluginState.Undefined;225 238 226 239 this.pluginDependencies[info] = pluginDependencies; … … 246 259 } else { 247 260 // no plugin description that matches the dependency name is available => plugin is disabled 248 desc. PluginState = PluginState.Disabled;261 desc.Disable(); 249 262 break; // stop processing more dependencies 250 263 } … … 257 270 if (IsAnyDependencyDisabled(pluginDescription)) { 258 271 // PluginDescription.Message = "Disabled: missing plugin dependency."; 259 pluginDescription. PluginState = PluginState.Disabled;272 pluginDescription.Disable(); 260 273 } 261 274 } … … 273 286 private void LoadPlugins(IEnumerable<PluginDescription> pluginDescriptions) { 274 287 // load all loadable plugins (all dependencies available) into the execution context 275 foreach (PluginDescription desc in PluginDescriptionIterator.IterateInDependencyOrder(pluginDescriptions.Where(x => x.PluginState != PluginState.Disabled))) { 288 foreach (var desc in PluginDescriptionIterator.IterateInDependencyOrder(pluginDescriptions 289 .Cast<IPluginDescription>() 290 .Where(x => x.PluginState != PluginState.Disabled))) { 276 291 List<Type> types = new List<Type>(); 277 292 foreach (string assembly in desc.Assemblies) { … … 288 303 IPlugin plugin = (IPlugin)Activator.CreateInstance(pluginType); 289 304 plugin.OnLoad(); 305 desc.Load(); 290 306 PluginAction(this, new PluginManagerActionEventArgs(plugin.Name, PluginManagerAction.PluginLoaded)); 291 307 } … … 335 351 if (!CheckPluginFiles(desc)) { 336 352 //plugin.Message = "Disabled: missing plugin file."; 337 desc. PluginState = PluginState.Disabled;353 desc.Disable(); 338 354 } 339 355 } -
branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure.Manager/PluginDescription.cs
r2481 r2488 30 30 /// </summary> 31 31 [Serializable] 32 public class PluginDescription {32 public class PluginDescription : IPluginDescription { 33 33 private string name; 34 34 /// <summary> … … 62 62 public PluginState PluginState { 63 63 get { return pluginState; } 64 set { pluginState = value; } 64 } 65 66 private int nTimesLoaded; 67 public void Disable() { 68 if (pluginState != PluginState.Undefined) 69 throw new InvalidOperationException("Can't disabled a plugin in state " + pluginState); 70 pluginState = PluginState.Disabled; 71 } 72 73 public void Enable() { 74 if (pluginState != PluginState.Undefined) 75 throw new InvalidOperationException("Can't enabled a plugin in state " + pluginState); 76 pluginState = PluginState.Enabled; 77 } 78 79 public void Load() { 80 if (!(pluginState == PluginState.Enabled || pluginState == PluginState.Loaded)) 81 throw new InvalidOperationException("Can't loaded a plugin in state " + pluginState); 82 pluginState = PluginState.Loaded; 83 nTimesLoaded++; 84 } 85 86 public void Unload() { 87 if (pluginState != PluginState.Loaded) 88 throw new InvalidOperationException("Can't unload a plugin in state " + pluginState); 89 nTimesLoaded--; 90 if (nTimesLoaded == 0) pluginState = PluginState.Enabled; 65 91 } 66 92 … … 78 104 } 79 105 80 private List< PluginDescription> dependencies = new List<PluginDescription>();106 private List<IPluginDescription> dependencies = new List<IPluginDescription>(); 81 107 /// <summary> 82 108 /// Gets all dependencies of the plugin. 83 109 /// </summary> 84 public IEnumerable< PluginDescription> Dependencies {110 public IEnumerable<IPluginDescription> Dependencies { 85 111 get { return dependencies; } 86 112 } … … 104 130 } 105 131 132 public PluginDescription() { 133 nTimesLoaded = 0; 134 pluginState = PluginState.Undefined; 135 } 136 137 106 138 //private string message; 107 139 ///// <summary> … … 121 153 } 122 154 123 // equals and hashcode have to be implemented because we want to compare PluginDescriptions from124 // different AppDomains and serialization destroys reference equality125 /// <summary>126 /// Checks whether the given object is equal to the current plugin.127 /// </summary>128 /// <param name="obj">The object to compare.</param>129 /// <returns><c>true</c> if it is equal, <c>false</c> otherwise.</returns>130 public override bool Equals(object obj) {131 if (!(obj is PluginDescription))132 return false;133 PluginDescription other = (PluginDescription)obj;155 //// equals and hashcode have to be implemented because we want to compare PluginDescriptions from 156 //// different AppDomains and serialization destroys reference equality 157 ///// <summary> 158 ///// Checks whether the given object is equal to the current plugin. 159 ///// </summary> 160 ///// <param name="obj">The object to compare.</param> 161 ///// <returns><c>true</c> if it is equal, <c>false</c> otherwise.</returns> 162 //public override bool Equals(object obj) { 163 // if (!(obj is PluginDescription)) 164 // return false; 165 // PluginDescription other = (PluginDescription)obj; 134 166 135 return other.Name == this.Name && other.Version == this.Version;136 }137 /// <summary>138 /// Gets the hash code of the current plugin.139 /// </summary>140 /// <returns>The hash code of the plugin.</returns>141 public override int GetHashCode() {142 if (version != null) {143 return name.GetHashCode() + version.GetHashCode();144 } else return name.GetHashCode();145 }167 // return other.Name == this.Name && other.Version == this.Version; 168 //} 169 ///// <summary> 170 ///// Gets the hash code of the current plugin. 171 ///// </summary> 172 ///// <returns>The hash code of the plugin.</returns> 173 //public override int GetHashCode() { 174 // if (version != null) { 175 // return name.GetHashCode() + version.GetHashCode(); 176 // } else return name.GetHashCode(); 177 //} 146 178 } 147 179 } -
branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure.Manager/PluginManager.cs
r2481 r2488 27 27 using System.Security.Permissions; 28 28 using System.Security; 29 using System.Linq; 29 30 30 31 namespace HeuristicLab.PluginInfrastructure.Manager { … … 81 82 82 83 private List<PluginDescription> plugins; 83 public IEnumerable<PluginDescription> Plugins {84 get { return plugins; }85 }84 //public IEnumerable<PluginDescription> Plugins { 85 // get { return plugins; } 86 //} 86 87 87 88 private List<ApplicationDescription> applications; … … 109 110 plugins = new List<PluginDescription>(remoteLoader.Plugins); 110 111 applications = new List<ApplicationDescription>(remoteLoader.Applications); 111 throw new NotImplementedException(); 112 113 // discard the AppDomain that was used for plugin discovery 114 UnloadAppDomain(pluginDomain); 115 } 116 117 private void UnloadAppDomain(AppDomain appDomain) { 118 AppDomain.Unload(appDomain); 119 120 // set all loaded plugins back to enabled 121 foreach (var pluginDescription in plugins) 122 pluginDescription.Unload(); 112 123 } 113 124 … … 130 141 public void Run(ApplicationDescription appInfo) { 131 142 // create a separate AppDomain for the application 132 // activate a PluginRunner instance in the application143 // initialize the static ApplicationManager in the AppDomain 133 144 // and remotely tell it to start the application 134 145 … … 139 150 setup.PrivateBinPath = pluginDir; 140 151 applicationDomain = AppDomain.CreateDomain(appInfo.Name, null, setup); 141 Runner remoteRunner = (Runner)applicationDomain.CreateInstanceAndUnwrap(typeof(Runner).Assembly.GetName().Name, typeof(Runner).FullName); 142 remoteRunner.PluginAction += delegate(object sender, PluginManagerActionEventArgs args) { if (Action != null) Action(this, args); }; 143 remoteRunner.LoadPlugins(Plugins); 152 ApplicationManager applicationManager = 153 (ApplicationManager)applicationDomain.CreateInstanceAndUnwrap("HeuristicLab.PluginInfraStructure.Manager", "HeuristicLab.PluginInfrastructure.Manager.ApplicationManager"); 154 //applicationManager.PluginAction += delegate(object sender, PluginManagerActionEventArgs args) { if (Action != null) Action(this, args); }; 155 applicationManager.PrepareApplicationDomain( 156 new List<IApplicationDescription>(applications.Cast<IApplicationDescription>()), 157 new List<IPluginDescription>(plugins.Cast<IPluginDescription>())); 144 158 NotifyListeners(PluginManagerAction.Initialized, "All plugins"); 145 remoteRunner.Run(appInfo);159 applicationManager.Run(appInfo); 146 160 } 147 161 finally { -
branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure.Manager/Runner.cs
r2481 r2488 44 44 } 45 45 46 public void LoadPlugins(IEnumerable< PluginDescription> pluginDescriptions) {46 public void LoadPlugins(IEnumerable<IPluginDescription> pluginDescriptions) { 47 47 //FileIOPermission fileperm = new FileIOPermission(FileIOPermissionAccess.AllAccess, @"C:\Program Files\HeuristicLab 3.0\plugins\"); 48 48 //fileperm.Assert(); 49 49 50 50 // load all loadable plugins (all dependencies available) into the execution context 51 foreach ( PluginDescriptiondesc in PluginDescriptionIterator.IterateInDependencyOrder(pluginDescriptions.Where(x => x.PluginState != PluginState.Disabled))) {51 foreach (var desc in PluginDescriptionIterator.IterateInDependencyOrder(pluginDescriptions.Where(x => x.PluginState != PluginState.Disabled))) { 52 52 List<Type> types = new List<Type>(); 53 53 foreach (string assembly in desc.Assemblies) { … … 64 64 IPlugin plugin = (IPlugin)Activator.CreateInstance(pluginType); 65 65 plugin.OnLoad(); 66 desc.Load(); 66 67 PluginAction(this, new PluginManagerActionEventArgs(plugin.Name, PluginManagerAction.PluginLoaded)); 67 68 } … … 88 89 89 90 public void Run(ApplicationDescription appInfo) { 90 IApplication runnablePlugin = (IApplication)Activator.CreateInstance(appInfo. PluginAssembly, appInfo.PluginType).Unwrap();91 IApplication runnablePlugin = (IApplication)Activator.CreateInstance(appInfo.DeclaringAssemblyName, appInfo.DeclaringTypeName).Unwrap(); 91 92 try { 92 93 runnablePlugin.Run();
Note: See TracChangeset
for help on using the changeset viewer.