#region License Information /* HeuristicLab * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab 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 * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . */ #endregion using System; using System.Collections.Generic; using System.Linq; using System.Reflection; namespace HeuristicLab.PluginInfrastructure { /// /// Lightweight application manager is set as the application manager as long as the plugin infrastructure is uninitialized. /// The list of plugins and applications is empty. The default application manager is necessary to provide the type discovery /// functionality in unit tests. /// internal sealed class LightweightApplicationManager : IApplicationManager { internal LightweightApplicationManager() { AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); } Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { return null; } #region IApplicationManager Members /// /// Gets an empty list of plugins. (LightweightApplicationManager doesn't support plugin discovery) /// public IEnumerable Plugins { get { return new IPluginDescription[0]; } } /// /// Gets an empty list of applications. (LightweightApplicationManager doesn't support application discovery) /// public IEnumerable Applications { get { return new IApplicationDescription[0]; } } /// /// Creates an instance of all types that are subtypes or the same type of the specified type /// /// Most general type. /// Enumerable of the created instances. public IEnumerable GetInstances() where T : class { return GetInstances(typeof(T)).Cast(); } /// /// Creates an instance of all types that are subtypes or the same type of the specified type /// /// Most general type. /// Enumerable of the created instances. public IEnumerable GetInstances(Type type) { List instances = new List(); foreach (Type t in GetTypes(type, true)) { object instance = null; try { instance = Activator.CreateInstance(t); } catch { } if (instance != null) instances.Add(instance); } return instances; } /// /// Finds all instantiable types that are subtypes or equal to the specified types. /// /// Most general types for which to find matching types. /// Return only types that are instantiable /// (interfaces, abstract classes... are not returned) /// Enumerable of the discovered types. public IEnumerable GetTypes(IEnumerable types, bool onlyInstantiable = true, bool assignableToAllTypes = true) { IEnumerable result = GetTypes(types.First(), onlyInstantiable); foreach (Type type in types.Skip(1)) { IEnumerable discoveredTypes = GetTypes(type, onlyInstantiable); if (assignableToAllTypes) result = result.Intersect(discoveredTypes); else result = result.Union(discoveredTypes); } return result; } /// /// Finds all types that are subtypes or equal to the specified type. /// /// Most general type for which to find matching types. /// Return only types that are instantiable /// (interfaces, abstract classes... are not returned) /// Enumerable of the discovered types. public IEnumerable GetTypes(Type type, bool onlyInstantiable = true) { return from asm in AppDomain.CurrentDomain.GetAssemblies() from t in GetTypes(type, asm, onlyInstantiable) select t; } /// /// Gets types that are assignable (same of subtype) to the specified type only from the given assembly. /// /// Most general type we want to find. /// Assembly that should be searched for types. /// Return only types that are instantiable /// (interfaces, abstract classes... are not returned) /// Enumerable of the discovered types. private static IEnumerable GetTypes(Type type, Assembly assembly, bool onlyInstantiable = true) { try { var assemblyTypes = assembly.GetTypes(); return from t in assemblyTypes where CheckTypeCompatibility(type, t) where onlyInstantiable == false || (!t.IsAbstract && !t.IsInterface && !t.HasElementType) where !IsNonDiscoverableType(t) select BuildType(t, type); } catch (TypeLoadException) { return Enumerable.Empty(); } catch (ReflectionTypeLoadException) { return Enumerable.Empty(); } } private static bool IsNonDiscoverableType(Type t) { return t.GetCustomAttributes(typeof(NonDiscoverableTypeAttribute), false).Any(); } private static bool CheckTypeCompatibility(Type type, Type other) { if (type.IsAssignableFrom(other)) return true; if (type.IsGenericType && other.IsGenericType) { try { if (type.IsAssignableFrom(other.GetGenericTypeDefinition().MakeGenericType(type.GetGenericArguments()))) return true; } catch (Exception) { } } return false; } private static Type BuildType(Type type, Type protoType) { if (type.IsGenericType && protoType.IsGenericType) return type.GetGenericTypeDefinition().MakeGenericType(protoType.GetGenericArguments()); else return type; } /// /// Not supported by the LightweightApplicationManager /// /// /// /// /// NotSupportedException public IEnumerable GetTypes(Type type, IPluginDescription plugin) { throw new NotSupportedException("LightweightApplicationManager doesn't support type discovery for plugins."); } /// /// Not supported by the LightweightApplicationManager /// /// /// /// /// /// NotSupportedException public IEnumerable GetTypes(Type type, IPluginDescription plugin, bool onlyInstantiable = true) { throw new NotSupportedException("LightweightApplicationManager doesn't support type discovery for plugins."); } /// /// Not supported by the LightweightApplicationManager /// /// /// /// /// /// NotSupportedException public IEnumerable GetTypes(IEnumerable types, IPluginDescription plugin, bool onlyInstantiable = true, bool assignableToAllTypes = true) { throw new NotSupportedException("LightweightApplicationManager doesn't support type discovery for plugins."); } /// /// Not supported by the LightweightApplicationManager /// /// /// /// NotSupportedException public IPluginDescription GetDeclaringPlugin(Type type) { throw new NotSupportedException("LightweightApplicationManager doesn't support type discovery for plugins."); } #endregion } }