#region CPL License /* Nuclex Framework Copyright (C) 2002-2012 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library 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 IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #endregion using System; using System.Diagnostics; using System.Reflection; namespace Nuclex.Support.Plugins { /// Integration host for plugins /// /// This class is created by the party that is interested in loading plugins, /// herein referred to as the "plugin user". The plugin host will monitor a /// repository and react to any assembly being loaded into that repository by /// iterating over all types (as in classes and structures) found in the /// assembly and using the employer to do whatever the plugin user intends /// to do with the types found in that assembly /// public class PluginHost { /// Initializes a plugin host using a new repository /// Employer used assess and employ the plugin types public PluginHost(Employer employer) : this(employer, new PluginRepository()) { } /// Initializes the plugin using an existing repository /// Employer used assess and employ the plugin types /// Repository in which plugins will be stored public PluginHost(Employer employer, PluginRepository repository) { this.employer = employer; this.repository = repository; foreach(Assembly assembly in this.repository.LoadedAssemblies) { employAssemblyTypes(assembly); } this.repository.AssemblyLoaded += new AssemblyLoadEventHandler(assemblyLoadHandler); } /// The repository containing all loaded plugins public PluginRepository Repository { get { return this.repository; } } /// The employer that is used by this plugin integration host public Employer Employer { get { return this.employer; } } /// Responds to a new plugin being loaded into the repository /// Repository into which the assembly was loaded /// Event arguments; contains the loaded assembly private void assemblyLoadHandler(object sender, AssemblyLoadEventArgs arguments) { employAssemblyTypes(arguments.LoadedAssembly); } /// Employs all employable types in an assembly /// Assembly whose types to assess and to employ private void employAssemblyTypes(Assembly assembly) { // Iterate all types contained in the assembly Type[] types = assembly.GetTypes(); for(int index = 0; index < types.Length; ++index) { Type type = types[index]; // We'll ignore abstract and non-public types if(!type.IsPublic || type.IsAbstract) { continue; } // Types that have been tagged with the [NoPlugin] attribute will be ignored if(type.HasAttribute()) { continue; } // Type seems to be acceptable, assess and possibly employ it try { if(this.employer.CanEmploy(type)) { this.employer.Employ(type); } } catch(Exception exception) { reportError("Could not employ " + type.ToString() + ": " + exception.Message); } } } /// Reports an error to the debugging console /// Error message that will be reported private static void reportError(string error) { #if WINDOWS Trace.WriteLine(error); #endif } /// Employs and manages types in the loaded plugin assemblies private Employer employer; /// Repository containing all plugins loaded, shared with other hosts private PluginRepository repository; } } // namespace Nuclex.Support.Plugins