#region License Information /* HeuristicLab * Copyright (C) 2002-2010 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.Reflection; using HeuristicLab.PluginInfrastructure; using System.Linq; using HeuristicLab.Common; namespace HeuristicLab.Clients.Hive.Slave { public static class PluginUtil { #region Required Plugin Search /// /// Returns a list of plugins in which the type itself and all members /// of the type are declared. Objectgraph is searched recursively. /// public static IEnumerable GetDeclaringPlugins(IDeepCloneable obj) { object clone = obj.Clone(); HashSet types = new HashSet(); HashSet objects = new HashSet(); string namespaceStart = "HeuristicLab."; FindTypesInObject(clone, objects, types, namespaceStart, 10); return GetDeclaringPlugins(types, namespaceStart); } /// /// Returns the plugins (including dependencies) in which the given types are declared /// public static IEnumerable GetDeclaringPlugins(IEnumerable types, string namespaceStart) { HashSet plugins = new HashSet(); var hlTypes = types.Where(x => x.Namespace != null && x.Namespace.StartsWith(namespaceStart)); foreach (Type t in hlTypes) { FindDeclaringPlugins(ApplicationManager.Manager.GetDeclaringPlugin(t), plugins); } return plugins; } /// /// Finds the dependencies of the given plugin and adds it to the plugins hashset. /// Also searches the dependencies recursively. /// public static void FindDeclaringPlugins(IPluginDescription plugin, HashSet plugins) { if (!plugins.Contains(plugin)) { plugins.Add(plugin); foreach (IPluginDescription dependency in plugin.Dependencies) { FindDeclaringPlugins(dependency, plugins); } } } /// /// Recursively finds all types used in type which are in a namespace which starts with namespaceStart /// Be aware that search is not performed on attributes /// /// the type to be searched /// found types will be stored there, needed in order to avoid duplicates public static void FindTypes(Type type, HashSet foundTypes, string namespaceStart, int nonNamespaceSearchDepth) { if (type.Namespace != null && type.Namespace.StartsWith(namespaceStart)) { nonNamespaceSearchDepth = 10; } else { nonNamespaceSearchDepth--; } if (!foundTypes.Contains(type) && nonNamespaceSearchDepth > 0) { foundTypes.Add(type); if (type.IsGenericType) { foreach (Type t in type.GetGenericArguments()) { FindTypes(t, foundTypes, namespaceStart, nonNamespaceSearchDepth); } } // constructors foreach (ConstructorInfo info in type.GetConstructors()) { foreach (ParameterInfo paramInfo in info.GetParameters()) { FindTypes(paramInfo.ParameterType, foundTypes, namespaceStart, nonNamespaceSearchDepth); } } // interfaces foreach (Type t in type.GetInterfaces()) { FindTypes(t, foundTypes, namespaceStart, nonNamespaceSearchDepth); } // events foreach (EventInfo info in type.GetEvents()) { FindTypes(info.EventHandlerType, foundTypes, namespaceStart, nonNamespaceSearchDepth); FindTypes(info.DeclaringType, foundTypes, namespaceStart, nonNamespaceSearchDepth); } // methods foreach (MethodInfo info in type.GetMethods()) { foreach (ParameterInfo paramInfo in info.GetParameters()) { FindTypes(paramInfo.ParameterType, foundTypes, namespaceStart, nonNamespaceSearchDepth); } FindTypes(info.ReturnType, foundTypes, namespaceStart, nonNamespaceSearchDepth); } // base type if (type.BaseType != null) { FindTypes(type.BaseType, foundTypes, namespaceStart, nonNamespaceSearchDepth); } } } public static void FindTypesInObject(object obj, HashSet visitedObjects, HashSet types, string namespaceStart, int nonNamespaceSearchDepth) { Type type = obj.GetType(); FindTypes(type, types, namespaceStart, nonNamespaceSearchDepth); if (type.Namespace != null && type.Namespace.StartsWith(namespaceStart)) { nonNamespaceSearchDepth = 10; } else { nonNamespaceSearchDepth--; } if (!visitedObjects.Contains(obj) && nonNamespaceSearchDepth > 0) { visitedObjects.Add(obj); // fields foreach (FieldInfo info in GetAllFields(type)) { var value = info.GetValue(obj); if (value == null) { FindTypes(info.FieldType, types, namespaceStart, nonNamespaceSearchDepth); } else { FindTypesInObject(value, visitedObjects, types, namespaceStart, nonNamespaceSearchDepth); } } } } public static IEnumerable GetAllFields(Type t) { BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy; return t.GetFields(flags); } #endregion } }