Free cookie consent management tool by TermsFeed Policy Generator

source: branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure.Manager/DefaultApplicationManager.cs @ 2498

Last change on this file since 2498 was 2497, checked in by gkronber, 15 years ago

Minor changes in plugin infrastructure. #799

File size: 8.9 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Security.Policy;
25using System.Reflection;
26using System.Diagnostics;
27using System.Security.Permissions;
28using System.Security;
29using System.Linq;
30using System.IO;
31
32namespace HeuristicLab.PluginInfrastructure.Manager {
33
34  public class DefaultApplicationManager : MarshalByRefObject, IApplicationManager {
35    internal event EventHandler<PluginInfrastructureEventArgs> PluginLoaded;
36    // cache for the AssemblyResolveEvent
37    // which must be handled when assemblies are loaded dynamically after the application start
38    private Dictionary<string, Assembly> loadedAssemblies;
39
40    private List<IPluginDescription> plugins;
41    /// <summary>
42    /// Gets all plugins.
43    /// </summary>
44    public IEnumerable<IPluginDescription> Plugins {
45      get { return plugins; }
46      internal set { plugins = new List<IPluginDescription>(value); }
47    }
48
49    private List<IApplicationDescription> applications;
50    /// <summary>
51    /// Gets all installed applications.
52    /// </summary>
53    public IEnumerable<IApplicationDescription> Applications {
54      get { return applications; }
55    }
56
57    public DefaultApplicationManager()
58      : base() {
59      loadedAssemblies = new Dictionary<string, Assembly>();
60      // needed for the special case when assemblies are loaded dynamically via LoadAssemblies()
61      AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => {
62        if (loadedAssemblies.ContainsKey(args.Name)) {
63          return loadedAssemblies[args.Name];
64        }
65        return null;
66      };
67    }
68
69    internal void PrepareApplicationDomain(IEnumerable<IApplicationDescription> apps, IEnumerable<IPluginDescription> plugins) {
70      this.plugins = new List<IPluginDescription>(plugins);
71      this.applications = new List<IApplicationDescription>(apps);
72      PluginInfrastructure.ApplicationManager.RegisterApplicationManager(this);
73      LoadPlugins(plugins);
74    }
75
76    private void LoadPlugins(IEnumerable<IPluginDescription> plugins) {
77      // load all loadable plugins (all dependencies available) into the execution context
78      foreach (var desc in PluginDescriptionIterator.IterateInDependencyOrder(plugins.Where(x => x.PluginState != PluginState.Disabled))) {
79        foreach (string assembly in desc.Assemblies) {
80          var asm = Assembly.LoadFrom(assembly);
81
82          // instantiate and load all plugins in this assembly
83          foreach (var plugin in GetInstances<IPlugin>(asm)) {
84            plugin.OnLoad();
85          }
86        }
87        FirePluginLoaded(desc);
88        desc.Load();
89      }
90    }
91
92    internal void Run(IApplicationDescription appInfo) {
93      IApplication runnablePlugin = (IApplication)Activator.CreateInstance(appInfo.DeclaringAssemblyName, appInfo.DeclaringTypeName).Unwrap();
94      try {
95        runnablePlugin.Run();
96      }
97      catch (Exception e) {
98        throw new Exception(String.Format(
99          "Unexpected exception caught: \"{0}\"\r\n" +
100          "Type: {1}\r\n" +
101          "Plugin {2}:\r\n{3}",
102          e.Message,
103          e.GetType().FullName,
104          appInfo.Name,
105          e.ToString()));
106      }
107    }
108
109    /// <summary>
110    /// Loads assemblies dynamically from a byte array
111    /// </summary>
112    /// <param name="plugins">bytearray of all assemblies that should be loaded</param>
113    public void LoadAssemblies(IEnumerable<byte[]> assemblies) {
114      foreach (byte[] asm in assemblies) {
115        Assembly loadedAsm = Assembly.Load(asm);
116        RegisterLoadedAssembly(loadedAsm);
117      }
118    }
119
120    // register assembly in the assembly cache for the AssemblyResolveEvent
121    private void RegisterLoadedAssembly(Assembly asm) {
122      loadedAssemblies.Add(asm.FullName, asm);
123      loadedAssemblies.Add(asm.GetName().Name, asm); // add short name
124    }
125
126    /// <summary>
127    /// Creates an instance of all types that are subtypes or the same type of the specified type and declared in <paramref name="plugin"/>
128    /// </summary>
129    /// <typeparam name="T">Most general type.</typeparam>
130    /// <returns>Enumerable of the created instances.</returns>
131    public IEnumerable<T> GetInstances<T>(IPluginDescription plugin) where T : class {
132      return from t in GetTypes(typeof(T), plugin)
133             where !t.IsAbstract && !t.IsInterface && !t.HasElementType
134             select (T)Activator.CreateInstance(t);
135    }
136    /// <summary>
137    /// Creates an instance of all types declared in assembly <param name="asm"/> that are subtypes or the same type of the specified type and declared in <paramref name="plugin"/>
138    /// </summary>
139    /// <typeparam name="T">Most general type.</typeparam>
140    /// <param name="asm">Declaring assembly.</param>
141    /// <returns>Enumerable of the created instances.</returns>
142    public IEnumerable<T> GetInstances<T>(Assembly asm) where T : class {
143      return from t in GetTypes(typeof(T), asm)
144             where !t.IsAbstract && !t.IsInterface && !t.HasElementType
145             select (T)Activator.CreateInstance(t);
146    }
147    /// <summary>
148    /// Creates an instance of all types that are subtypes or the same type of the specified type
149    /// </summary>
150    /// <typeparam name="T">Most general type.</typeparam>
151    /// <returns>Enumerable of the created instances.</returns>
152    public IEnumerable<T> GetInstances<T>() where T : class {
153      return from i in GetInstances(typeof(T))
154             select (T)i;
155    }
156
157    /// <summary>
158    /// Creates an instance of all types that are subtypes or the same type of the specified type
159    /// </summary>
160    /// <typeparam name="type">Most general type.</typeparam>
161    /// <returns>Enumerable of the created instances.</returns>
162    public IEnumerable<object> GetInstances(Type type) {
163      return from t in GetTypes(type)
164             where !t.IsAbstract && !t.IsInterface && !t.HasElementType
165             select Activator.CreateInstance(t);
166    }
167
168    /// <summary>
169    /// Finds all types that are subtypes or equal to the specified type.
170    /// </summary>
171    /// <param name="type">Most general type for which to find matching types.</param>
172    /// <returns>Enumerable of the discovered types.</returns>
173    public IEnumerable<Type> GetTypes(Type type) {
174      return from asm in AppDomain.CurrentDomain.GetAssemblies()
175             from t in GetTypes(type, asm)
176             select t;
177    }
178
179    /// <summary>
180    /// Finds all types that are subtypes or equal to the specified type if they are part of the given
181    /// <paramref name="plugin"/>.
182    /// </summary>
183    /// <param name="type">Most general type for which to find matching types.</param>
184    /// <param name="plugin">The plugin the subtypes must be part of.</param>
185    /// <returns>Enumerable of the discovered types.</returns>
186    public IEnumerable<Type> GetTypes(Type type, IPluginDescription pluginDescription) {
187      return from asm in AppDomain.CurrentDomain.GetAssemblies()
188             where pluginDescription.Assemblies.Any(asmPath => Path.GetFullPath(asmPath) == Path.GetFullPath(asm.Location))
189             from t in GetTypes(type, asm)
190             select t;
191    }
192
193    /// <summary>
194    /// Gets types that are assignable (same of subtype) to the specified type only from the given assembly.
195    /// </summary>
196    /// <param name="type">Most general type we want to find.</param>
197    /// <param name="assembly">Assembly that should be searched for types.</param>
198    /// <returns>Enumerable of the discovered types.</returns>
199    private IEnumerable<Type> GetTypes(Type type, Assembly assembly) {
200      return from t in assembly.GetTypes()
201             where type.IsAssignableFrom(t)
202             select t;
203    }
204
205    private void FirePluginLoaded(IPluginDescription plugin) {
206      if (PluginLoaded != null) PluginLoaded(this, new PluginInfrastructureEventArgs("Plugin loaded", plugin));
207    }
208
209    // infinite lease time
210    /// <summary>
211    /// Initializes the life time service with infinite lease time.
212    /// </summary>
213    /// <returns><c>null</c>.</returns>
214    public override object InitializeLifetimeService() {
215      return null;
216    }
217  }
218}
219
Note: See TracBrowser for help on using the repository browser.