Changeset 1229
- Timestamp:
- 02/26/09 13:44:15 (16 years ago)
- Location:
- trunk/sources/HeuristicLab.PluginInfrastructure
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/sources/HeuristicLab.PluginInfrastructure/BaseClasses/PluginBase.cs
r1189 r1229 30 30 /// Default implementation of the IPlugin interface. 31 31 /// </summary> 32 public class PluginBase : IPlugin {32 public abstract class PluginBase : IPlugin { 33 33 private string name; 34 34 private Version version; … … 47 47 48 48 // exactly one attribute of the type ClassInfoAttribute must be given 49 if (pluginAttributes.Length != 1) {49 if (pluginAttributes.Length != 1) { 50 50 throw new InvalidPluginException(); 51 51 } … … 55 55 56 56 // if the plugin name is not explicitly set in the attribute then the default plugin name is the FullName of the type 57 if (pluginAttribute != null && pluginAttribute.Name != null) {57 if (pluginAttribute != null && pluginAttribute.Name != null) { 58 58 this.name = pluginAttribute.Name; 59 59 } else { … … 62 62 63 63 // if the version is not explicitly set in the attribute then the version of the assembly is used as default 64 if (pluginAttribute != null && pluginAttribute.Version != null) {64 if (pluginAttribute != null && pluginAttribute.Version != null) { 65 65 this.version = new Version(pluginAttribute.Version); 66 66 } else { … … 69 69 70 70 // if the description is not explicitly set in the attribute then the name of name of the plugin is used as default 71 if (pluginAttribute != null && pluginAttribute.Description != null) {71 if (pluginAttribute != null && pluginAttribute.Description != null) { 72 72 this.description = pluginAttribute.Description; 73 73 } else { … … 81 81 this.files = new string[fileAttributes.Length]; 82 82 int i = 0; 83 foreach (PluginFileAttribute fileAttr in fileAttributes) {83 foreach (PluginFileAttribute fileAttr in fileAttributes) { 84 84 files[i++] = fileAttr.Filename; 85 85 } … … 121 121 } 122 122 123 /// <inheritdoc/> 124 public virtual void OnInstall() { 125 } 126 127 /// <inheritdoc/> 128 public virtual void OnDelete() { 129 } 130 131 /// <inheritdoc/> 132 public virtual void OnPreUpdate() { 133 } 134 135 /// <inheritdoc/> 136 public virtual void OnPostUpdate() { 137 } 123 /// <inhertidoc> 124 public virtual void OnLoad() { } 125 /// <inhertidoc> 126 public virtual void OnInstall() { } 127 /// <inhertidoc> 128 public virtual void OnDelete() { } 129 /// <inhertidoc> 130 public virtual void OnPreUpdate() { } 131 /// <inhertidoc> 132 public virtual void OnPostUpdate() { } 138 133 139 134 #endregion -
trunk/sources/HeuristicLab.PluginInfrastructure/Interfaces/IPlugin.cs
r2 r1229 30 30 /// assemblies of the plugin. Plugin developers can use the properties of this interface to store 31 31 /// plugin data (name, version, files, update location ...). 32 /// The methods On Install(), OnDelete(), OnPreUpdate(), OnPostUpdate() are called by the framework32 /// The methods OnLoad(), OnInstall(), OnDelete(), OnPreUpdate(), OnPostUpdate() are called by the framework 33 33 /// when the corresponding actions are executed. This mechanism allows that the plugin reacts to such 34 34 /// events. For instance to store plugin specific settings. … … 42 42 string[] Files { get; } 43 43 44 45 /// <summary> 46 /// Called by the framework whenever the plugin is loaded. 47 /// Plugins are loaded once at startup and then each time a new application is started from the starter. 48 /// </summary> 49 void OnLoad(); 44 50 /// <summary> 45 51 /// called by the framework after the plugin was successfully installed -
trunk/sources/HeuristicLab.PluginInfrastructure/Loader.cs
r1189 r1229 51 51 get { 52 52 List<PluginInfo> list = new List<PluginInfo>(); 53 foreach (PluginInfo info in allPlugins.Keys) {54 if (!disabledPlugins.Exists(delegate(PluginInfo disabledInfo) { return info.Name == disabledInfo.Name; })) {53 foreach (PluginInfo info in allPlugins.Keys) { 54 if (!disabledPlugins.Exists(delegate(PluginInfo disabledInfo) { return info.Name == disabledInfo.Name; })) { 55 55 list.Add(info); 56 56 } … … 80 80 81 81 private IPlugin FindPlugin(PluginInfo plugin) { 82 if (allPlugins.ContainsKey(plugin)) {82 if (allPlugins.ContainsKey(plugin)) { 83 83 return allPlugins[plugin]; 84 84 } else return null; … … 101 101 try { 102 102 return Assembly.ReflectionOnlyLoad(args.Name); 103 } catch(FileLoadException ex) { 103 } 104 catch (FileLoadException ex) { 104 105 return null; 105 106 } 106 107 }; 107 108 allPlugins.Clear(); 108 109 disabledPlugins.Clear(); … … 121 122 applications = new List<ApplicationInfo>(); 122 123 123 foreach (IApplication application in apps) {124 foreach (IApplication application in apps) { 124 125 ApplicationInfo info = new ApplicationInfo(); 125 126 info.Name = application.Name; … … 137 138 List<Assembly> assemblies = new List<Assembly>(); 138 139 // load all installed plugins into the reflection only context 139 foreach (String filename in Directory.GetFiles(pluginDir, "*.dll")) {140 foreach (String filename in Directory.GetFiles(pluginDir, "*.dll")) { 140 141 try { 141 142 assemblies.Add(ReflectionOnlyLoadDll(filename)); 142 } catch(BadImageFormatException) { } // just ignore the case that the .dll file is not actually a CLR dll 143 } 144 catch (BadImageFormatException) { } // just ignore the case that the .dll file is not actually a CLR dll 143 145 } 144 146 return assemblies; … … 150 152 151 153 private void CheckAssemblyDependencies(List<Assembly> assemblies) { 152 foreach (Assembly assembly in assemblies) {154 foreach (Assembly assembly in assemblies) { 153 155 // GetExportedTypes throws FileNotFoundException when a referenced assembly 154 156 // of the current assembly is missing. … … 156 158 Type[] exported = assembly.GetExportedTypes(); 157 159 158 foreach (Type t in exported) {160 foreach (Type t in exported) { 159 161 // if there is a type that implements IPlugin 160 if (Array.Exists<Type>(t.GetInterfaces(), delegate(Type iface) {162 if (Array.Exists<Type>(t.GetInterfaces(), delegate(Type iface) { 161 163 // use AssemblyQualifiedName to compare the types because we can't directly 162 164 // compare ReflectionOnly types and Execution types … … 167 169 } 168 170 } 169 } catch(FileNotFoundException ex) { 171 } 172 catch (FileNotFoundException ex) { 170 173 PluginInfo info = new PluginInfo(); 171 174 AssemblyName name = assembly.GetName(); … … 176 179 info.Message = "File not found: " + ex.FileName; 177 180 disabledPlugins.Add(info); 178 } catch(FileLoadException ex) { 181 } 182 catch (FileLoadException ex) { 179 183 PluginInfo info = new PluginInfo(); 180 184 AssemblyName name = assembly.GetName(); … … 203 207 string pluginName = ""; 204 208 // iterate through all custom attributes and search for named arguments that we are interested in 205 foreach (CustomAttributeData attributeData in attributes) {209 foreach (CustomAttributeData attributeData in attributes) { 206 210 List<CustomAttributeNamedArgument> namedArguments = new List<CustomAttributeNamedArgument>(attributeData.NamedArguments); 207 211 // if the current attribute contains a named argument with the name "Name" then extract the plugin name … … 209 213 return arg.MemberInfo.Name == "Name"; 210 214 }); 211 if (pluginNameArgument.MemberInfo != null) {215 if (pluginNameArgument.MemberInfo != null) { 212 216 pluginName = (string)pluginNameArgument.TypedValue.Value; 213 217 } … … 217 221 return arg.MemberInfo.Name == "Dependency"; 218 222 }); 219 if (dependencyNameArgument.MemberInfo != null) {223 if (dependencyNameArgument.MemberInfo != null) { 220 224 pluginDependencies.Add((string)dependencyNameArgument.TypedValue.Value); 221 225 } … … 228 232 return arg.MemberInfo.Name == "Filetype"; 229 233 }); 230 if (filenameArg.MemberInfo != null && filetypeArg.MemberInfo != null) {234 if (filenameArg.MemberInfo != null && filetypeArg.MemberInfo != null) { 231 235 pluginFiles.Add(pluginDir + "/" + (string)filenameArg.TypedValue.Value); 232 if ((PluginFileType)filetypeArg.TypedValue.Value == PluginFileType.Assembly) {236 if ((PluginFileType)filetypeArg.TypedValue.Value == PluginFileType.Assembly) { 233 237 pluginAssemblies.Add(pluginDir + "/" + (string)filenameArg.TypedValue.Value); 234 238 } … … 237 241 238 242 // minimal sanity check of the attribute values 239 if (pluginName != "" && pluginAssemblies.Count > 0) {243 if (pluginName != "" && pluginAssemblies.Count > 0) { 240 244 // create a temporary PluginInfo that contains the attribute values 241 245 PluginInfo info = new PluginInfo(); … … 253 257 254 258 private void CheckPluginDependencies() { 255 foreach (PluginInfo pluginInfo in preloadedPluginInfos) {259 foreach (PluginInfo pluginInfo in preloadedPluginInfos) { 256 260 // don't need to check plugins that are already disabled 257 if (disabledPlugins.Contains(pluginInfo)) {261 if (disabledPlugins.Contains(pluginInfo)) { 258 262 continue; 259 263 } 260 264 visitedDependencies.Clear(); 261 if (!CheckPluginDependencies(pluginInfo.Name)) {265 if (!CheckPluginDependencies(pluginInfo.Name)) { 262 266 PluginInfo matchingInfo = preloadedPluginInfos.Find(delegate(PluginInfo info) { return info.Name == pluginInfo.Name; }); 263 if (matchingInfo == null) throw new InvalidProgramException(); // shouldn't happen264 foreach (string dependency in pluginDependencies[matchingInfo]) {267 if (matchingInfo == null) throw new InvalidProgramException(); // shouldn't happen 268 foreach (string dependency in pluginDependencies[matchingInfo]) { 265 269 PluginInfo dependencyInfo = new PluginInfo(); 266 270 dependencyInfo.Name = dependency; … … 276 280 private List<string> visitedDependencies = new List<string>(); 277 281 private bool CheckPluginDependencies(string pluginName) { 278 if (!preloadedPluginInfos.Exists(delegate(PluginInfo info) { return pluginName == info.Name; }) ||282 if (!preloadedPluginInfos.Exists(delegate(PluginInfo info) { return pluginName == info.Name; }) || 279 283 disabledPlugins.Exists(delegate(PluginInfo info) { return pluginName == info.Name; }) || 280 284 visitedDependencies.Contains(pluginName)) { … … 286 290 287 291 PluginInfo matchingInfo = preloadedPluginInfos.Find(delegate(PluginInfo info) { return info.Name == pluginName; }); 288 if (matchingInfo == null) throw new InvalidProgramException(); // shouldn't happen289 foreach (string dependency in pluginDependencies[matchingInfo]) {292 if (matchingInfo == null) throw new InvalidProgramException(); // shouldn't happen 293 foreach (string dependency in pluginDependencies[matchingInfo]) { 290 294 visitedDependencies.Add(pluginName); 291 if (CheckPluginDependencies(dependency) == false) {295 if (CheckPluginDependencies(dependency) == false) { 292 296 // if only one dependency is not available that means that the current plugin also is unloadable 293 297 return false; … … 304 308 private void LoadPlugins() { 305 309 // load all loadable plugins (all dependencies available) into the execution context 306 foreach (PluginInfo pluginInfo in preloadedPluginInfos) {307 if (!disabledPlugins.Contains(pluginInfo)) {308 foreach (string assembly in pluginInfo.Assemblies) {310 foreach (PluginInfo pluginInfo in preloadedPluginInfos) { 311 if (!disabledPlugins.Contains(pluginInfo)) { 312 foreach (string assembly in pluginInfo.Assemblies) { 309 313 Assembly.LoadFrom(assembly); 310 314 } … … 314 318 DiscoveryService service = new DiscoveryService(); 315 319 // now search and instantiate an IPlugin type in each loaded assembly 316 foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) {320 foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) { 317 321 // don't search for plugins in the PluginInfrastructure 318 if (assembly == this.GetType().Assembly)322 if (assembly == this.GetType().Assembly) 319 323 continue; 320 324 Type[] availablePluginTypes = service.GetTypes(typeof(IPlugin), assembly); 321 foreach (Type pluginType in availablePluginTypes) {322 if (!pluginType.IsAbstract && !pluginType.IsInterface && !pluginType.HasElementType) {325 foreach (Type pluginType in availablePluginTypes) { 326 if (!pluginType.IsAbstract && !pluginType.IsInterface && !pluginType.HasElementType) { 323 327 IPlugin plugin = (IPlugin)Activator.CreateInstance(pluginType); 324 328 PluginAction(this, new PluginManagerActionEventArgs(plugin.Name, PluginManagerAction.InitializingPlugin)); 329 plugin.OnLoad(); 325 330 pluginsByName.Add(plugin.Name, plugin); 326 331 } … … 328 333 } 329 334 330 foreach (IPlugin plugin in pluginsByName.Values) {335 foreach (IPlugin plugin in pluginsByName.Values) { 331 336 PluginInfo pluginInfo = GetPluginInfo(plugin); 332 337 allPlugins.Add(pluginInfo, plugin); … … 335 340 } 336 341 private PluginInfo GetPluginInfo(IPlugin plugin) { 337 if (pluginInfos.ContainsKey(plugin)) {342 if (pluginInfos.ContainsKey(plugin)) { 338 343 return pluginInfos[plugin]; 339 344 } … … 344 349 345 350 object[] customAttributes = plugin.GetType().Assembly.GetCustomAttributes(typeof(AssemblyBuildDateAttribute), false); 346 if (customAttributes.Length > 0) {351 if (customAttributes.Length > 0) { 347 352 pluginInfo.BuildDate = ((AssemblyBuildDateAttribute)customAttributes[0]).BuildDate; 348 353 } … … 357 362 358 363 PluginInfo preloadedInfo = preloadedPluginInfos.Find(delegate(PluginInfo info) { return info.Name == plugin.Name; }); 359 foreach (string assembly in preloadedInfo.Assemblies) {364 foreach (string assembly in preloadedInfo.Assemblies) { 360 365 // always use \ as directory separator (this is necessary for discovery of types in 361 366 // plugins see DiscoveryService.GetTypes() 362 367 pluginInfo.Assemblies.Add(assembly.Replace('/', '\\')); 363 368 } 364 foreach (string dependency in pluginDependencies[preloadedInfo]) {369 foreach (string dependency in pluginDependencies[preloadedInfo]) { 365 370 // accumulate the dependencies of each assembly into the dependencies of the whole plugin 366 371 PluginInfo dependencyInfo = GetPluginInfo(pluginsByName[dependency]); … … 372 377 373 378 private void CheckPluginFiles() { 374 foreach (PluginInfo plugin in preloadedPluginInfos) {375 if (!CheckPluginFiles(plugin)) {379 foreach (PluginInfo plugin in preloadedPluginInfos) { 380 if (!CheckPluginFiles(plugin)) { 376 381 plugin.Message = "Disabled: missing plugin file."; 377 382 disabledPlugins.Add(plugin); … … 381 386 382 387 private bool CheckPluginFiles(PluginInfo pluginInfo) { 383 foreach (string filename in pluginInfo.Files) {384 if (!File.Exists(filename)) {385 if (MissingPluginFile != null) {388 foreach (string filename in pluginInfo.Files) { 389 if (!File.Exists(filename)) { 390 if (MissingPluginFile != null) { 386 391 MissingPluginFile(pluginInfo.Name, filename); 387 392 } … … 402 407 internal void OnDelete(PluginInfo pluginInfo) { 403 408 IPlugin plugin = FindPlugin(pluginInfo); 404 if (plugin!=null) plugin.OnDelete();409 if (plugin != null) plugin.OnDelete(); 405 410 } 406 411 407 412 internal void OnInstall(PluginInfo pluginInfo) { 408 413 IPlugin plugin = FindPlugin(pluginInfo); 409 if (plugin != null) plugin.OnInstall();414 if (plugin != null) plugin.OnInstall(); 410 415 } 411 416 412 417 internal void OnPreUpdate(PluginInfo pluginInfo) { 413 418 IPlugin plugin = FindPlugin(pluginInfo); 414 if (plugin != null) plugin.OnPreUpdate();419 if (plugin != null) plugin.OnPreUpdate(); 415 420 } 416 421 417 422 internal void OnPostUpdate(PluginInfo pluginInfo) { 418 423 IPlugin plugin = FindPlugin(pluginInfo); 419 if (plugin != null) plugin.OnPostUpdate();424 if (plugin != null) plugin.OnPostUpdate(); 420 425 } 421 426 } -
trunk/sources/HeuristicLab.PluginInfrastructure/Runner.cs
r1189 r1229 39 39 } 40 40 //CodeAccessPermission.RevertAssert(); 41 FireOnLoad(); 41 42 PluginManager.Manager.LoadedPlugins = plugins; 42 43 } … … 45 46 IApplication runnablePlugin = (IApplication)Activator.CreateInstance(appInfo.PluginAssembly, appInfo.PluginType).Unwrap(); 46 47 runnablePlugin.Run(); 48 } 49 50 private void FireOnLoad() { 51 DiscoveryService service = new DiscoveryService(); 52 Array.ForEach(service.GetInstances<IPlugin>(), p => p.OnLoad()); 47 53 } 48 54
Note: See TracChangeset
for help on using the changeset viewer.