Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.PluginInfrastructure/3.3/LightweightApplicationManager.cs @ 5352

Last change on this file since 5352 was 5131, checked in by swagner, 14 years ago

Fixed exceptions in plugin infrastructure when trying to instantiate types which do not provide a parameterless constructor (#1309).

File size: 7.5 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 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.Linq;
25using System.Reflection;
26
27namespace HeuristicLab.PluginInfrastructure {
28
29  /// <summary>
30  /// Lightweight application manager is set as the application manager as long as the plugin infrastructure is uninitialized.
31  /// The list of plugins and applications is empty. The default application manager is necessary to provide the type discovery
32  /// functionality in unit tests.
33  /// </summary>
34  internal sealed class LightweightApplicationManager : IApplicationManager {
35    internal LightweightApplicationManager() {
36      AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
37    }
38
39    Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) {
40      return null;
41    }
42
43
44    #region IApplicationManager Members
45    /// <summary>
46    /// Gets an empty list of plugins. (LightweightApplicationManager doesn't support plugin discovery)
47    /// </summary>
48    public IEnumerable<IPluginDescription> Plugins {
49      get { return new IPluginDescription[0]; }
50    }
51
52    /// <summary>
53    /// Gets an empty list of applications. (LightweightApplicationManager doesn't support application discovery)
54    /// </summary>
55    public IEnumerable<IApplicationDescription> Applications {
56      get { return new IApplicationDescription[0]; }
57    }
58
59    /// <summary>
60    /// Creates an instance of all types that are subtypes or the same type of the specified type
61    /// </summary>
62    /// <typeparam name="T">Most general type.</typeparam>
63    /// <returns>Enumerable of the created instances.</returns>
64    public IEnumerable<T> GetInstances<T>() where T : class {
65      return GetInstances(typeof(T)).Cast<T>();
66    }
67
68    /// <summary>
69    /// Creates an instance of all types that are subtypes or the same type of the specified type
70    /// </summary>
71    /// <param name="type">Most general type.</param>
72    /// <returns>Enumerable of the created instances.</returns>
73    public IEnumerable<object> GetInstances(Type type) {
74      List<object> instances = new List<object>();
75      foreach (Type t in GetTypes(type, true)) {
76        object instance = null;
77        try { instance = Activator.CreateInstance(t); }
78        catch { }
79        if (instance != null) instances.Add(instance);
80      }
81      return instances;
82    }
83
84
85    /// <summary>
86    /// Finds all instantiable types that are subtypes or equal to the specified type.
87    /// </summary>
88    /// <param name="type">Most general type for which to find matching types.</param>
89    /// <remarks>Return only types that are instantiable
90    /// (interfaces, abstract classes... are not returned)</remarks>
91    /// <returns>Enumerable of the discovered types.</returns>
92    public IEnumerable<Type> GetTypes(Type type) {
93      return GetTypes(type, true);
94    }
95
96    /// <summary>
97    /// Finds all types that are subtypes or equal to the specified type.
98    /// </summary>
99    /// <param name="type">Most general type for which to find matching types.</param>
100    /// <param name="onlyInstantiable">Return only types that are instantiable
101    /// (interfaces, abstract classes... are not returned)</param>
102    /// <returns>Enumerable of the discovered types.</returns>
103    public IEnumerable<Type> GetTypes(Type type, bool onlyInstantiable) {
104      return from asm in AppDomain.CurrentDomain.GetAssemblies()
105             from t in GetTypes(type, asm, onlyInstantiable)
106             select t;
107    }
108
109    /// <summary>
110    /// Gets types that are assignable (same of subtype) to the specified type only from the given assembly.
111    /// </summary>
112    /// <param name="type">Most general type we want to find.</param>
113    /// <param name="assembly">Assembly that should be searched for types.</param>
114    /// <param name="onlyInstantiable">Return only types that are instantiable
115    /// (interfaces, abstract classes...  are not returned)</param>
116    /// <returns>Enumerable of the discovered types.</returns>
117    private static IEnumerable<Type> GetTypes(Type type, Assembly assembly, bool onlyInstantiable) {
118      try {
119        var assemblyTypes = assembly.GetTypes();
120
121        return from t in assemblyTypes
122               where CheckTypeCompatibility(type, t)
123               where onlyInstantiable == false || (!t.IsAbstract && !t.IsInterface && !t.HasElementType)
124               select BuildType(t, type);
125      }
126      catch (TypeLoadException) {
127        return Enumerable.Empty<Type>();
128      }
129      catch (ReflectionTypeLoadException) {
130        return Enumerable.Empty<Type>();
131      }
132    }
133
134    private static bool CheckTypeCompatibility(Type type, Type other) {
135      if (type.IsAssignableFrom(other))
136        return true;
137      if (type.IsGenericType && other.IsGenericType) {
138        try {
139          if (type.IsAssignableFrom(other.GetGenericTypeDefinition().MakeGenericType(type.GetGenericArguments())))
140            return true;
141        }
142        catch (Exception) { }
143      }
144      return false;
145    }
146    private static Type BuildType(Type type, Type protoType) {
147      if (type.IsGenericType && protoType.IsGenericType)
148        return type.GetGenericTypeDefinition().MakeGenericType(protoType.GetGenericArguments());
149      else
150        return type;
151    }
152
153    /// <summary>
154    /// Not supported by the LightweightApplicationManager
155    /// </summary>
156    /// <param name="type"></param>
157    /// <param name="plugin"></param>
158    /// <returns></returns>
159    /// <throws>NotSupportedException</throws>
160    public IEnumerable<Type> GetTypes(Type type, IPluginDescription plugin) {
161      throw new NotSupportedException("LightweightApplicationManager doesn't support type discovery for plugins.");
162    }
163
164    /// <summary>
165    /// Not supported by the LightweightApplicationManager
166    /// </summary>
167    /// <param name="type"></param>
168    /// <param name="plugin"></param>
169    /// <param name="onlyInstantiable"></param>
170    /// <returns></returns>
171    /// <throws>NotSupportedException</throws>
172    public IEnumerable<Type> GetTypes(Type type, IPluginDescription plugin, bool onlyInstantiable) {
173      throw new NotSupportedException("LightweightApplicationManager doesn't support type discovery for plugins.");
174    }
175
176    /// <summary>
177    /// Not supported by the LightweightApplicationManager
178    /// </summary>
179    /// <param name="type"></param>
180    /// <returns></returns>
181    /// <throws>NotSupportedException</throws>
182    public IPluginDescription GetDeclaringPlugin(Type type) {
183      throw new NotSupportedException("LightweightApplicationManager doesn't support type discovery for plugins.");
184    }
185
186    #endregion
187  }
188}
Note: See TracBrowser for help on using the repository browser.