[5105] | 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 |
|
---|
| 22 | using System;
|
---|
| 23 | using System.Collections.Generic;
|
---|
| 24 | using System.Reflection;
|
---|
| 25 | using HeuristicLab.PluginInfrastructure;
|
---|
| 26 | using System.Linq;
|
---|
| 27 | using HeuristicLab.Common;
|
---|
| 28 |
|
---|
| 29 | namespace HeuristicLab.Clients.Hive.Slave {
|
---|
| 30 | public static class PluginUtil {
|
---|
| 31 | #region Required Plugin Search
|
---|
| 32 |
|
---|
| 33 | /// <summary>
|
---|
| 34 | /// Returns a list of plugins in which the type itself and all members
|
---|
| 35 | /// of the type are declared. Objectgraph is searched recursively.
|
---|
| 36 | /// </summary>
|
---|
| 37 | public static IEnumerable<IPluginDescription> GetDeclaringPlugins(IDeepCloneable obj) {
|
---|
| 38 | object clone = obj.Clone();
|
---|
| 39 | HashSet<Type> types = new HashSet<Type>();
|
---|
| 40 | HashSet<object> objects = new HashSet<object>();
|
---|
| 41 | string namespaceStart = "HeuristicLab.";
|
---|
| 42 | FindTypesInObject(clone, objects, types, namespaceStart, 10);
|
---|
| 43 | return GetDeclaringPlugins(types, namespaceStart);
|
---|
| 44 | }
|
---|
| 45 |
|
---|
| 46 | /// <summary>
|
---|
| 47 | /// Returns the plugins (including dependencies) in which the given types are declared
|
---|
| 48 | /// </summary>
|
---|
| 49 | public static IEnumerable<IPluginDescription> GetDeclaringPlugins(IEnumerable<Type> types, string namespaceStart) {
|
---|
| 50 | HashSet<IPluginDescription> plugins = new HashSet<IPluginDescription>();
|
---|
| 51 | var hlTypes = types.Where(x => x.Namespace != null && x.Namespace.StartsWith(namespaceStart));
|
---|
| 52 | foreach (Type t in hlTypes) {
|
---|
| 53 | FindDeclaringPlugins(ApplicationManager.Manager.GetDeclaringPlugin(t), plugins);
|
---|
| 54 | }
|
---|
| 55 | return plugins;
|
---|
| 56 | }
|
---|
| 57 |
|
---|
| 58 | /// <summary>
|
---|
| 59 | /// Finds the dependencies of the given plugin and adds it to the plugins hashset.
|
---|
| 60 | /// Also searches the dependencies recursively.
|
---|
| 61 | /// </summary>
|
---|
| 62 | public static void FindDeclaringPlugins(IPluginDescription plugin, HashSet<IPluginDescription> plugins) {
|
---|
| 63 | if (!plugins.Contains(plugin)) {
|
---|
| 64 | plugins.Add(plugin);
|
---|
| 65 | foreach (IPluginDescription dependency in plugin.Dependencies) {
|
---|
| 66 | FindDeclaringPlugins(dependency, plugins);
|
---|
| 67 | }
|
---|
| 68 | }
|
---|
| 69 | }
|
---|
| 70 |
|
---|
| 71 | /// <summary>
|
---|
| 72 | /// Recursively finds all types used in type which are in a namespace which starts with namespaceStart
|
---|
| 73 | /// Be aware that search is not performed on attributes
|
---|
| 74 | /// </summary>
|
---|
| 75 | /// <param name="type">the type to be searched</param>
|
---|
| 76 | /// <param name="foundTypes">found types will be stored there, needed in order to avoid duplicates</param>
|
---|
| 77 | public static void FindTypes(Type type, HashSet<Type> foundTypes, string namespaceStart, int nonNamespaceSearchDepth) {
|
---|
| 78 | if (type.Namespace != null && type.Namespace.StartsWith(namespaceStart)) {
|
---|
| 79 | nonNamespaceSearchDepth = 10;
|
---|
| 80 | } else {
|
---|
| 81 | nonNamespaceSearchDepth--;
|
---|
| 82 | }
|
---|
| 83 |
|
---|
| 84 | if (!foundTypes.Contains(type) && nonNamespaceSearchDepth > 0) {
|
---|
| 85 | foundTypes.Add(type);
|
---|
| 86 |
|
---|
| 87 | if (type.IsGenericType) {
|
---|
| 88 | foreach (Type t in type.GetGenericArguments()) {
|
---|
| 89 | FindTypes(t, foundTypes, namespaceStart, nonNamespaceSearchDepth);
|
---|
| 90 | }
|
---|
| 91 | }
|
---|
| 92 |
|
---|
| 93 | // constructors
|
---|
| 94 | foreach (ConstructorInfo info in type.GetConstructors()) {
|
---|
| 95 | foreach (ParameterInfo paramInfo in info.GetParameters()) {
|
---|
| 96 | FindTypes(paramInfo.ParameterType, foundTypes, namespaceStart, nonNamespaceSearchDepth);
|
---|
| 97 | }
|
---|
| 98 | }
|
---|
| 99 |
|
---|
| 100 | // interfaces
|
---|
| 101 | foreach (Type t in type.GetInterfaces()) {
|
---|
| 102 | FindTypes(t, foundTypes, namespaceStart, nonNamespaceSearchDepth);
|
---|
| 103 | }
|
---|
| 104 |
|
---|
| 105 | // events
|
---|
| 106 | foreach (EventInfo info in type.GetEvents()) {
|
---|
| 107 | FindTypes(info.EventHandlerType, foundTypes, namespaceStart, nonNamespaceSearchDepth);
|
---|
| 108 | FindTypes(info.DeclaringType, foundTypes, namespaceStart, nonNamespaceSearchDepth);
|
---|
| 109 | }
|
---|
| 110 |
|
---|
| 111 | // methods
|
---|
| 112 | foreach (MethodInfo info in type.GetMethods()) {
|
---|
| 113 | foreach (ParameterInfo paramInfo in info.GetParameters()) {
|
---|
| 114 | FindTypes(paramInfo.ParameterType, foundTypes, namespaceStart, nonNamespaceSearchDepth);
|
---|
| 115 | }
|
---|
| 116 | FindTypes(info.ReturnType, foundTypes, namespaceStart, nonNamespaceSearchDepth);
|
---|
| 117 | }
|
---|
| 118 |
|
---|
| 119 | // base type
|
---|
| 120 | if (type.BaseType != null) {
|
---|
| 121 | FindTypes(type.BaseType, foundTypes, namespaceStart, nonNamespaceSearchDepth);
|
---|
| 122 | }
|
---|
| 123 | }
|
---|
| 124 | }
|
---|
| 125 |
|
---|
| 126 | public static void FindTypesInObject(object obj, HashSet<object> visitedObjects, HashSet<Type> types, string namespaceStart, int nonNamespaceSearchDepth) {
|
---|
| 127 | Type type = obj.GetType();
|
---|
| 128 | FindTypes(type, types, namespaceStart, nonNamespaceSearchDepth);
|
---|
| 129 |
|
---|
| 130 | if (type.Namespace != null && type.Namespace.StartsWith(namespaceStart)) {
|
---|
| 131 | nonNamespaceSearchDepth = 10;
|
---|
| 132 | } else {
|
---|
| 133 | nonNamespaceSearchDepth--;
|
---|
| 134 | }
|
---|
| 135 |
|
---|
| 136 | if (!visitedObjects.Contains(obj) && nonNamespaceSearchDepth > 0) {
|
---|
| 137 | visitedObjects.Add(obj);
|
---|
| 138 |
|
---|
| 139 | // fields
|
---|
| 140 | foreach (FieldInfo info in GetAllFields(type)) {
|
---|
| 141 | var value = info.GetValue(obj);
|
---|
| 142 | if (value == null) {
|
---|
| 143 | FindTypes(info.FieldType, types, namespaceStart, nonNamespaceSearchDepth);
|
---|
| 144 | } else {
|
---|
| 145 | FindTypesInObject(value, visitedObjects, types, namespaceStart, nonNamespaceSearchDepth);
|
---|
| 146 | }
|
---|
| 147 | }
|
---|
| 148 | }
|
---|
| 149 | }
|
---|
| 150 |
|
---|
| 151 | public static IEnumerable<FieldInfo> GetAllFields(Type t) {
|
---|
| 152 | BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy;
|
---|
| 153 | return t.GetFields(flags);
|
---|
| 154 | }
|
---|
| 155 | #endregion
|
---|
| 156 | }
|
---|
| 157 | }
|
---|