Free cookie consent management tool by TermsFeed Policy Generator

Changeset 2503


Ignore:
Timestamp:
11/17/09 14:03:40 (15 years ago)
Author:
gkronber
Message:

Moved classes from project PluginInfrastructure.Manager to PluginInfrastructure make it easier to declare strict accessibility constraints. #799

Location:
branches/PluginInfrastructure Refactoring
Files:
1 added
1 deleted
6 edited
6 moved

Legend:

Unmodified
Added
Removed
  • branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure.Manager/HeuristicLab.PluginInfrastructure.Manager.csproj

    r2497 r2503  
    5050    <Compile Include="ApplicationDescription.cs" />
    5151    <Compile Include="DefaultApplicationManager.cs" />
    52     <Compile Include="Loader.cs" />
    5352    <Compile Include="PluginDescription.cs" />
    5453    <Compile Include="PluginInfrastructureEventArgs.cs" />
    5554    <Compile Include="PluginManager.cs" />
     55    <Compile Include="PluginValidator.cs" />
    5656    <Compile Include="Properties\AssemblyInfo.cs" />
    5757  </ItemGroup>
  • branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure/ApplicationManager.cs

    r2495 r2503  
    3131namespace HeuristicLab.PluginInfrastructure {
    3232
     33  /// <summary>
     34  /// The ApplicationManager has a reference to the application manager singleton.
     35  /// The application manager provides
     36  /// </summary>
    3337  public static class ApplicationManager {
    3438    private static IApplicationManager appManager;
     39    /// <summary>
     40    /// Gets the application manager singleton.
     41    /// </summary>
    3542    public static IApplicationManager Manager {
    3643      get { return appManager; }
    3744    }
    3845
    39     public static void RegisterApplicationManager(IApplicationManager manager) {
     46    /// <summary>
     47    /// Registers a new application manager.
     48    /// </summary>
     49    /// <param name="manager"></param>
     50    internal static void RegisterApplicationManager(IApplicationManager manager) {
    4051      if (appManager != null) throw new InvalidOperationException("The application manager has already been set.");
    4152      appManager = manager;
  • branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure/BaseClasses/PluginBase.cs

    r2488 r2503  
    5656    }
    5757
    58     ///// <inheritdoc />
    59     //public Version Version {
    60     //  get {
    61     //    var pluginAttribute = PluginDescriptionAttribute;
    62     //    // if the version is not set in the attribute then the version of the assembly is used as default
    63     //    if (string.IsNullOrEmpty(pluginAttribute.Version)) {
    64     //      return this.GetType().Assembly.GetName().Version;
    65     //    } else {
    66     //      return new Version(pluginAttribute.Version);
    67     //    }
    68     //  }
    69     //}
    70 
    71     ///// <inheritdoc />
    72     //public string Description {
    73     //  get {
    74     //    var pluginAttribute = PluginDescriptionAttribute;
    75     //    // if the description is not explicitly set in the attribute then the name of the plugin is used as default
    76     //    if (string.IsNullOrEmpty(pluginAttribute.Description)) {
    77     //      return pluginAttribute.Name;
    78     //    } else {
    79     //      return pluginAttribute.Description;
    80     //    }
    81     //  }
    82     //}
    8358
    8459    /// <inheritdoc/>
     
    9469    /// <inhertitdoc>
    9570    public virtual void OnLoad() { }
     71    /// <inhertitdoc>
     72    public virtual void OnUnload() { }
    9673    #endregion
    9774
  • branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure/DefaultApplicationManager.cs

    r2502 r2503  
    3232namespace HeuristicLab.PluginInfrastructure.Manager {
    3333
    34   public class DefaultApplicationManager : MarshalByRefObject, IApplicationManager {
     34  public sealed class DefaultApplicationManager : MarshalByRefObject, IApplicationManager {
    3535    internal event EventHandler<PluginInfrastructureEventArgs> PluginLoaded;
     36    internal event EventHandler<PluginInfrastructureEventArgs> PluginUnloaded;
     37
    3638    // cache for the AssemblyResolveEvent
    3739    // which must be handled when assemblies are loaded dynamically after the application start
    3840    private Dictionary<string, Assembly> loadedAssemblies;
    3941
     42    private List<IPlugin> loadedPlugins;
     43
    4044    private List<IPluginDescription> plugins;
    4145    /// <summary>
     
    5559    }
    5660
    57     public DefaultApplicationManager()
     61    internal DefaultApplicationManager()
    5862      : base() {
    5963      loadedAssemblies = new Dictionary<string, Assembly>();
     64      loadedPlugins = new List<IPlugin>();
    6065      // needed for the special case when assemblies are loaded dynamically via LoadAssemblies()
    6166      AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => {
     
    8388          foreach (var plugin in GetInstances<IPlugin>(asm)) {
    8489            plugin.OnLoad();
     90            loadedPlugins.Add(plugin);
    8591          }
    8692        }
    87         FirePluginLoaded(desc);
     93        OnPluginLoaded(new PluginInfrastructureEventArgs("Plugin loaded", desc));
    8894        desc.Load();
    8995      }
     
    105111          e.ToString()));
    106112      }
     113      finally {
     114        // unload plugins in reverse order
     115        foreach (var plugin in loadedPlugins.Reverse<IPlugin>()) {
     116          plugin.OnUnload();
     117        }
     118        foreach (var desc in PluginDescriptionIterator.IterateInDependencyOrder(plugins.Where(x => x.PluginState != PluginState.Disabled))) {
     119          desc.Unload();
     120          OnPluginUnloaded(new PluginInfrastructureEventArgs("Plugin unloaded", desc));
     121        }
     122      }
    107123    }
    108124
     
    203219    }
    204220
    205     private void FirePluginLoaded(IPluginDescription plugin) {
    206       if (PluginLoaded != null) PluginLoaded(this, new PluginInfrastructureEventArgs("Plugin loaded", plugin));
     221    private void OnPluginLoaded(PluginInfrastructureEventArgs e) {
     222      if (PluginLoaded != null) PluginLoaded(this, e);
     223    }
     224
     225    private void OnPluginUnloaded(PluginInfrastructureEventArgs e) {
     226      if (PluginUnloaded != null) PluginUnloaded(this, e);
    207227    }
    208228
  • branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure/HeuristicLab.PluginInfrastructure.csproj

    r2488 r2503  
    8686  </ItemGroup>
    8787  <ItemGroup>
     88    <Compile Include="ApplicationDescription.cs" />
    8889    <Compile Include="Attributes\ApplicationAttribute.cs" />
    8990    <Compile Include="Attributes\AssemblyBuildDateAttribute.cs" />
     
    9394    <Compile Include="BaseClasses\ApplicationBase.cs" />
    9495    <Compile Include="BaseClasses\PluginBase.cs" />
     96    <Compile Include="DefaultApplicationManager.cs" />
    9597    <Compile Include="Interfaces\IApplicationManager.cs" />
    9698    <Compile Include="Interfaces\IApplicationDescription.cs" />
     
    102104    <Compile Include="Interfaces\IPluginDescription.cs" />
    103105    <Compile Include="InvalidPluginException.cs" />
     106    <Compile Include="PluginDescription.cs" />
    104107    <Compile Include="PluginDescriptionIterator.cs" />
    105108    <Compile Include="ApplicationManager.cs" />
     109    <Compile Include="PluginInfrastructureEventArgs.cs" />
     110    <Compile Include="PluginManager.cs" />
    106111    <Compile Include="PluginState.cs" />
     112    <Compile Include="PluginValidator.cs" />
    107113    <Compile Include="Properties\AssemblyInfo.cs" />
    108114    <EmbeddedResource Include="Properties\Resources.resx">
     
    129135    </Compile>
    130136  </ItemGroup>
     137  <ItemGroup>
     138    <Folder Include="Manager\" />
     139  </ItemGroup>
    131140  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
    132141  <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
  • branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure/Interfaces/IPlugin.cs

    r2481 r2503  
    5151    /// </summary>
    5252    void OnLoad();
     53
     54    /// <summary>
     55    /// Called by the framework whenever the plugin is unloaded.
     56    /// Plugins are unloaded when an application exits.
     57    /// </summary>
     58    void OnUnload();
    5359  }
    5460}
  • branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure/PluginInfrastructureEventArgs.cs

    r2502 r2503  
    2424using System.Text;
    2525
    26 namespace HeuristicLab.PluginInfrastructure {
     26namespace HeuristicLab.PluginInfrastructure.Manager {
    2727  // to be replaced by GenericEventArgs
    2828  [Serializable]
  • branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure/PluginManager.cs

    r2502 r2503  
    3535  /// Class to manage different plugins.
    3636  /// </summary>
    37   public class PluginManager : MarshalByRefObject {
     37  public sealed class PluginManager : MarshalByRefObject {
    3838    /// <summary>
    3939    /// Event handler for actions in the plugin manager.
     
    4242
    4343    private string pluginDir;
    44 
    45     public PluginManager(string pluginDir) {
    46       this.pluginDir = pluginDir;
    47     }
    4844
    4945    private List<PluginDescription> plugins;
     
    5753    }
    5854
     55    private object locker = new object();
     56    private bool initialized;
     57
     58    public PluginManager(string pluginDir) {
     59      this.pluginDir = pluginDir;
     60      plugins = new List<PluginDescription>();
     61      applications = new List<ApplicationDescription>();
     62      Reset();
     63    }
     64
     65    public void Reset() {
     66      initialized = false;
     67      if (plugins != null && plugins.Any(x => x.PluginState == PluginState.Loaded)) throw new InvalidOperationException("Reset() is not allowed while applications are active.");
     68      plugins.Clear();
     69      applications.Clear();
     70    }
     71
    5972    /// <summary>
    6073    /// Determines installed plugins and checks if all plugins are loadable.
    6174    /// </summary>
    6275    public void DiscoverAndCheckPlugins() {
    63       FireAction("Initializing", "PluginInfrastructure");
     76      OnAction(new PluginInfrastructureEventArgs("Initializing", "PluginInfrastructure"));
    6477      AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
    6578      setup.PrivateBinPath = pluginDir;
     
    6780      try {
    6881        pluginDomain = AppDomain.CreateDomain("plugin domain", null, setup);
    69         Loader remoteLoader = (Loader)pluginDomain.CreateInstanceAndUnwrap("HeuristicLab.PluginInfraStructure.Manager", "HeuristicLab.PluginInfrastructure.Manager.Loader");
    70         remoteLoader.PluginDir = pluginDir;
    71         // forward all events from the remoteLoader to listeners
    72         remoteLoader.PluginLoaded += delegate(object sender, PluginInfrastructureEventArgs args) { FireAction(args.Action, args.Entity); };
    73         this.plugins = new List<PluginDescription>(remoteLoader.Plugins);
    74         this.applications = new List<ApplicationDescription>(remoteLoader.Applications);
    75         FireAction("Initialized", "PluginInfrastructure");
     82        PluginValidator remoteValidator = (PluginValidator)pluginDomain.CreateInstanceAndUnwrap("HeuristicLab.PluginInfraStructure.Manager", "HeuristicLab.PluginInfrastructure.Manager.Loader");
     83        remoteValidator.PluginDir = pluginDir;
     84        // forward all events from the remoteValidator to listeners
     85        remoteValidator.PluginLoaded +=
     86          delegate(object sender, PluginInfrastructureEventArgs e) {
     87            OnAction(e);
     88          };
     89        // get list of plugins and applications from the validator
     90        plugins.Clear(); applications.Clear();
     91        plugins.AddRange(remoteValidator.Plugins);
     92        applications.AddRange(remoteValidator.Applications);
     93        OnAction(new PluginInfrastructureEventArgs("Initialized", "PluginInfrastructure"));
    7694      }
    7795      finally {
    7896        // discard the AppDomain that was used for plugin discovery
    79         UnloadAppDomain(pluginDomain);
     97        AppDomain.Unload(pluginDomain);
     98        // unload all plugins
     99        foreach (var pluginDescription in plugins)
     100          pluginDescription.Unload();
     101        initialized = true;
    80102      }
    81103    }
     
    83105
    84106    /// <summary>
    85     /// Creates a separate AppDomain.
    86     /// Loads all active plugin assemblies and starts the application in the new AppDomain via a PluginRunner instance activated in the new AppDomain
     107    /// Starts and application in a separate AppDomain.
     108    /// Loads all enabled plugins and starts the application via a PluginRunner instance activated in the new AppDomain.
    87109    /// </summary>
    88110    /// <param name="appInfo">application to run</param>
    89111    public void Run(ApplicationDescription appInfo) {
     112      if (!initialized) throw new InvalidOperationException("PluginManager is not initialized. DiscoverAndCheckPlugins() must be called before Run()");
    90113      // create a separate AppDomain for the application
    91114      // initialize the static ApplicationManager in the AppDomain
    92115      // and remotely tell it to start the application
    93116
    94       FireAction("Starting application", appInfo.Name);
     117      OnAction(new PluginInfrastructureEventArgs("Starting application", appInfo));
    95118      AppDomain applicationDomain = null;
    96119      try {
     
    101124          (DefaultApplicationManager)applicationDomain.CreateInstanceAndUnwrap("HeuristicLab.PluginInfraStructure.Manager", "HeuristicLab.PluginInfrastructure.Manager.DefaultApplicationManager");
    102125        applicationManager.PluginLoaded += applicationManager_PluginLoaded;
     126        applicationManager.PluginUnloaded += applicationManager_PluginUnloaded;
    103127        applicationManager.PrepareApplicationDomain(
    104128          new List<IApplicationDescription>(applications.Cast<IApplicationDescription>()),
    105129          new List<IPluginDescription>(plugins.Cast<IPluginDescription>()));
    106         FireAction("Started application", appInfo.Name);
     130        OnAction(new PluginInfrastructureEventArgs("Started application", appInfo));
    107131        applicationManager.Run(appInfo);
    108132      }
    109133      finally {
    110134        // make sure domain is unloaded in all cases
    111         UnloadAppDomain(applicationDomain);
     135        AppDomain.Unload(applicationDomain);
    112136      }
    113137    }
    114138
    115     void applicationManager_PluginLoaded(object sender, PluginInfrastructureEventArgs e) {
     139    private void applicationManager_PluginUnloaded(object sender, PluginInfrastructureEventArgs e) {
     140      // unload the matching plugin description (
     141      PluginDescription desc = (PluginDescription)e.Entity;
     142
     143      // access to plugin descriptions has to be synchronized because multiple applications
     144      // can be started or stopped at the same time
     145      lock (locker) {
     146        plugins.First(x => x.Equals(desc)).Unload();
     147      }
     148      OnAction(new PluginInfrastructureEventArgs(e.Action, e.Entity));
     149    }
     150
     151    private void applicationManager_PluginLoaded(object sender, PluginInfrastructureEventArgs e) {
    116152      // load the matching plugin description (
    117153      PluginDescription desc = (PluginDescription)e.Entity;
    118       foreach (var myDesc in plugins) {
    119         if (myDesc.Equals(desc)) myDesc.Load();
     154      // access to plugin descriptions has to be synchronized because multiple applications
     155      // can be started or stopped at the same time
     156      lock (locker) {
     157        plugins.First(x => x.Equals(desc)).Load();
    120158      }
    121       FireAction(e.Action, e.Entity);
     159      OnAction(new PluginInfrastructureEventArgs(e.Action, e.Entity));
    122160    }
    123161
    124     private void UnloadAppDomain(AppDomain appDomain) {
    125       AppDomain.Unload(appDomain);
    126 
    127       // TODO: Update plugin descriptions in all active AppDomains
    128 
    129       // unload all plugins
    130       foreach (var pluginDescription in plugins)
    131         pluginDescription.Unload();
    132     }
    133 
    134     private void FireAction(string action, object entity) {
     162    private void OnAction(PluginInfrastructureEventArgs e) {
    135163      if (Action != null) {
    136         Action(this, new PluginInfrastructureEventArgs(action, entity));
     164        Action(this, e);
    137165      }
    138166    }
  • branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure/PluginValidator.cs

    r2497 r2503  
    3030
    3131namespace HeuristicLab.PluginInfrastructure.Manager {
    32   internal class Loader : MarshalByRefObject {
     32  /// <summary>
     33  /// Discovers all installed plugins in the plugin directory. Checks correctness of plugin meta-data and if
     34  /// all plugin files are available and checks plugin dependencies.
     35  /// </summary>
     36  internal sealed class PluginValidator : MarshalByRefObject {
    3337    internal event EventHandler<PluginInfrastructureEventArgs> PluginLoaded;
    3438
     
    3842    internal IEnumerable<ApplicationDescription> Applications {
    3943      get {
     44        if (string.IsNullOrEmpty(PluginDir)) throw new InvalidOperationException("PluginDir is not set.");
    4045        if (applications == null) DiscoverAndCheckPlugins();
    4146        return applications;
     
    4651    internal IEnumerable<PluginDescription> Plugins {
    4752      get {
     53        if (string.IsNullOrEmpty(PluginDir)) throw new InvalidOperationException("PluginDir is not set.");
    4854        if (plugins == null) DiscoverAndCheckPlugins();
    4955        return plugins;
     
    5359    public string PluginDir { get; set; }
    5460
    55     public Loader() {
     61    public PluginValidator() {
    5662      this.pluginDependencies = new Dictionary<PluginDescription, List<string>>();
    5763
     
    6975    /// Init first clears all internal datastructures (including plugin lists)
    7076    /// 1. All assemblies in the plugins directory are loaded into the reflection only context.
    71     /// 2. The loader checks if all necessary files for each plugin are available.
    72     /// 3. The loaded builds the tree of plugin descriptions (dependencies)
    73     /// 4. The loader checks if all dependencies for each plugin are ok.
     77    /// 2. The validator checks if all necessary files for each plugin are available.
     78    /// 3. The validator builds the tree of plugin descriptions (dependencies)
     79    /// 4. The validator checks if all dependencies for each plugin are ok.
    7480    /// 5. All plugins for which there are no dependencies missing are loaded into the execution context.
    7581    /// 6. Each loaded plugin (all assemblies) is searched for a types that implement IPlugin
     
    7783    /// 7. All types implementing IApplication are discovered
    7884    /// </summary>
    79     private void DiscoverAndCheckPlugins() {
     85    internal void DiscoverAndCheckPlugins() {
    8086      pluginDependencies.Clear();
    8187
     
    135141          assemblies.Add(Assembly.ReflectionOnlyLoadFrom(filename));
    136142        }
    137         catch (BadImageFormatException) { } // just ignore the case that the .dll file is not actually a CLR dll
     143        catch (BadImageFormatException) { } // just ignore the case that the .dll file is not a CLR assembly (e.g. a native dll)
    138144      }
    139145      return assemblies;
     
    243249      foreach (PluginDescription pluginDescription in pluginDescriptions.Where(x => x.PluginState != PluginState.Disabled)) {
    244250        if (IsAnyDependencyDisabled(pluginDescription)) {
    245           // PluginDescription.Message = "Disabled: missing plugin dependency.";
    246251          pluginDescription.Disable();
    247252        }
     
    277282            IPlugin plugin = (IPlugin)Activator.CreateInstance(pluginType);
    278283            plugin.OnLoad();
    279             FirePluginLoaded(plugin.Name);
     284            OnPluginLoaded(new PluginInfrastructureEventArgs("Plugin loaded", plugin.Name));
    280285          }
    281286        }
     
    302307    }
    303308
    304     private void FirePluginLoaded(string pluginName) {
     309    internal void OnPluginLoaded(PluginInfrastructureEventArgs e) {
    305310      if (PluginLoaded != null)
    306         PluginLoaded(this, new PluginInfrastructureEventArgs("Plugin loaded", pluginName));
     311        PluginLoaded(this, e);
    307312    }
    308313
  • branches/PluginInfrastructure Refactoring/HeuristicLab/HeuristicLab.csproj

    r2481 r2503  
    127127  </ItemGroup>
    128128  <ItemGroup>
    129     <ProjectReference Include="..\HeuristicLab.PluginInfrastructure.Manager\HeuristicLab.PluginInfrastructure.Manager.csproj">
    130       <Project>{CA8AAD91-E8E2-41AF-96AD-2BA94BC3EF2D}</Project>
    131       <Name>HeuristicLab.PluginInfrastructure.Manager</Name>
    132     </ProjectReference>
    133129    <ProjectReference Include="..\HeuristicLab.PluginInfrastructure\HeuristicLab.PluginInfrastructure.csproj">
    134130      <Project>{94186A6A-5176-4402-AE83-886557B53CCA}</Project>
Note: See TracChangeset for help on using the changeset viewer.