Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
05/14/11 16:45:46 (13 years ago)
Author:
abeham
Message:

#1465

  • updated branch with latest version of trunk
Location:
branches/histogram
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/histogram

  • branches/histogram/HeuristicLab.PluginInfrastructure/3.3/DefaultApplicationManager.cs

    r6022 r6195  
    2121
    2222using System;
    23 using System.Collections.Generic;
    24 using System.IO;
    25 using System.Linq;
    26 using System.Reflection;
    27 using HeuristicLab.PluginInfrastructure.Manager;
    2823
    2924namespace HeuristicLab.PluginInfrastructure {
    3025
    31   /// <summary>
    32   /// The DefaultApplicationManager provides properties to retrieve the list of available plugins and applications.
    33   /// It also provides methods for type discovery and instantiation for types declared in plugins.
     26  /// <summary> 
    3427  /// The DefaultApplicationManager is registered as ApplicationManager.Manager singleton for each HL application
    3528  /// started via the plugin infrastructure.
    3629  /// </summary>
    37   internal sealed class DefaultApplicationManager : MarshalByRefObject, IApplicationManager {
    38     /// <summary>
    39     /// Fired when a plugin is loaded.
    40     /// </summary>
    41     internal event EventHandler<PluginInfrastructureEventArgs> PluginLoaded;
    42     /// <summary>
    43     /// Fired when a plugin is unloaded (when the application terminates).
    44     /// </summary>
    45     internal event EventHandler<PluginInfrastructureEventArgs> PluginUnloaded;
    46 
    47     // cache for the AssemblyResolveEvent
    48     // which must be handled when assemblies are loaded dynamically after the application start
    49     private Dictionary<string, Assembly> loadedAssemblies;
    50 
    51     private List<IPlugin> loadedPlugins;
    52 
    53     private List<PluginDescription> plugins;
    54     /// <summary>
    55     /// Gets all plugins.
    56     /// </summary>
    57     public IEnumerable<IPluginDescription> Plugins {
    58       get { return plugins.Cast<IPluginDescription>(); }
    59     }
    60 
    61     private List<ApplicationDescription> applications;
    62     /// <summary>
    63     /// Gets all installed applications.
    64     /// </summary>
    65     public IEnumerable<IApplicationDescription> Applications {
    66       get { return applications.Cast<IApplicationDescription>(); }
    67     }
     30  internal sealed class DefaultApplicationManager : SandboxApplicationManager {
    6831
    6932    internal DefaultApplicationManager()
    7033      : base() {
    71       loadedAssemblies = new Dictionary<string, Assembly>();
    72       loadedPlugins = new List<IPlugin>();
    7334      AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => {
    7435        if (loadedAssemblies.ContainsKey(args.Name)) {
     
    7940    }
    8041
    81     /// <summary>
    82     /// Prepares the application domain for the execution of an HL application.
    83     /// Pre-loads all <paramref name="plugins"/>.
    84     /// </summary>
    85     /// <param name="apps">Enumerable of available HL applications.</param>
    86     /// <param name="plugins">Enumerable of plugins that should be pre-loaded.</param>
    87     internal void PrepareApplicationDomain(IEnumerable<ApplicationDescription> apps, IEnumerable<PluginDescription> plugins) {
    88       this.plugins = new List<PluginDescription>(plugins);
    89       this.applications = new List<ApplicationDescription>(apps);
    90       ApplicationManager.RegisterApplicationManager(this);
    91       LoadPlugins(plugins);
    92     }
    93 
    94     /// <summary>
    95     /// Loads the <paramref name="plugins"/> into this application domain.
    96     /// </summary>
    97     /// <param name="plugins">Enumerable of plugins that should be loaded.</param>
    98     private void LoadPlugins(IEnumerable<PluginDescription> plugins) {
    99       // load all loadable plugins (all dependencies available) into the execution context
    100       foreach (var desc in PluginDescriptionIterator.IterateDependenciesBottomUp(plugins.Where(x => x.PluginState != PluginState.Disabled))) {
    101         foreach (string fileName in desc.AssemblyLocations) {
    102           // load assembly reflection only first to get the full assembly name
    103           var reflectionOnlyAssembly = Assembly.ReflectionOnlyLoadFrom(fileName);
    104           // load the assembly into execution context using full assembly name
    105           var asm = Assembly.Load(reflectionOnlyAssembly.FullName);
    106           RegisterLoadedAssembly(asm);
    107           // instantiate and load all plugins in this assembly
    108           foreach (var plugin in GetInstances<IPlugin>(asm)) {
    109             plugin.OnLoad();
    110             loadedPlugins.Add(plugin);
    111           }
    112         }
    113         OnPluginLoaded(new PluginInfrastructureEventArgs(desc));
    114         desc.Load();
    115       }
    116     }
    117 
    118     /// <summary>
    119     /// Runs the application declared in <paramref name="appInfo"/>.
    120     /// This is a synchronous call. When the application is terminated all plugins are unloaded.
    121     /// </summary>
    122     /// <param name="appInfo">Description of the application to run</param>
    123     internal void Run(ApplicationDescription appInfo) {
    124       IApplication runnablePlugin = (IApplication)Activator.CreateInstance(appInfo.DeclaringAssemblyName, appInfo.DeclaringTypeName).Unwrap();
    125       try {
    126         runnablePlugin.Run();
    127       }
    128       finally {
    129         // unload plugins in reverse order
    130         foreach (var plugin in loadedPlugins.Reverse<IPlugin>()) {
    131           plugin.OnUnload();
    132         }
    133         foreach (var desc in PluginDescriptionIterator.IterateDependenciesBottomUp(plugins.Where(x => x.PluginState != PluginState.Disabled))) {
    134           desc.Unload();
    135           OnPluginUnloaded(new PluginInfrastructureEventArgs(desc));
    136         }
    137       }
    138     }
    139 
    140     /// <summary>
    141     /// Loads raw assemblies dynamically from a byte array
    142     /// </summary>
    143     /// <param name="assemblies">bytearray of all raw assemblies that should be loaded</param>
    144     internal void LoadAssemblies(IEnumerable<byte[]> assemblies) {
    145       foreach (byte[] asm in assemblies) {
    146         Assembly loadedAsm = Assembly.Load(asm);
    147         RegisterLoadedAssembly(loadedAsm);
    148       }
    149     }
    150 
    151     // register assembly in the assembly cache for the AssemblyResolveEvent
    152     private void RegisterLoadedAssembly(Assembly asm) {
    153       if (loadedAssemblies.ContainsKey(asm.FullName) || loadedAssemblies.ContainsKey(asm.GetName().Name)) {
    154         throw new ArgumentException("An assembly with the name " + asm.GetName().Name + " has been registered already.", "asm");
    155       }
    156       loadedAssemblies.Add(asm.FullName, asm);
    157       loadedAssemblies.Add(asm.GetName().Name, asm); // add short name
    158     }
    159 
    160     /// <summary>
    161     /// Creates an instance of all types that are subtypes or the same type of the specified type and declared in <paramref name="plugin"/>
    162     /// </summary>
    163     /// <typeparam name="T">Most general type.</typeparam>
    164     /// <returns>Enumerable of the created instances.</returns>
    165     internal static IEnumerable<T> GetInstances<T>(IPluginDescription plugin) where T : class {
    166       List<T> instances = new List<T>();
    167       foreach (Type t in GetTypes(typeof(T), plugin, true)) {
    168         T instance = null;
    169         try { instance = (T)Activator.CreateInstance(t); }
    170         catch { }
    171         if (instance != null) instances.Add(instance);
    172       }
    173       return instances;
    174     }
    175     /// <summary>
    176     /// Creates an instance of all types declared in assembly <paramref name="asm"/> that are subtypes or the same type of the specified <typeparamref name="type"/>.
    177     /// </summary>
    178     /// <typeparam name="T">Most general type.</typeparam>
    179     /// <param name="asm">Declaring assembly.</param>
    180     /// <returns>Enumerable of the created instances.</returns>
    181     private static IEnumerable<T> GetInstances<T>(Assembly asm) where T : class {
    182       List<T> instances = new List<T>();
    183       foreach (Type t in GetTypes(typeof(T), asm, true)) {
    184         T instance = null;
    185         try { instance = (T)Activator.CreateInstance(t); }
    186         catch { }
    187         if (instance != null) instances.Add(instance);
    188       }
    189       return instances;
    190     }
    191     /// <summary>
    192     /// Creates an instance of all types that are subtypes or the same type of the specified type
    193     /// </summary>
    194     /// <typeparam name="T">Most general type.</typeparam>
    195     /// <returns>Enumerable of the created instances.</returns>
    196     internal static IEnumerable<T> GetInstances<T>() where T : class {
    197       return from i in GetInstances(typeof(T))
    198              select (T)i;
    199     }
    200 
    201     /// <summary>
    202     /// Creates an instance of all types that are subtypes or the same type of the specified type
    203     /// </summary>
    204     /// <param name="type">Most general type.</param>
    205     /// <returns>Enumerable of the created instances.</returns>
    206     internal static IEnumerable<object> GetInstances(Type type) {
    207       List<object> instances = new List<object>();
    208       foreach (Type t in GetTypes(type, true)) {
    209         object instance = null;
    210         try { instance = Activator.CreateInstance(t); }
    211         catch { }
    212         if (instance != null) instances.Add(instance);
    213       }
    214       return instances;
    215     }
    216 
    217     /// <summary>
    218     /// Finds all types that are subtypes or equal to the specified type.
    219     /// </summary>
    220     /// <param name="type">Most general type for which to find matching types.</param>
    221     /// <param name="onlyInstantiable">Return only types that are instantiable
    222     /// (interfaces, abstract classes... are not returned)</param>
    223     /// <returns>Enumerable of the discovered types.</returns>
    224     internal static IEnumerable<Type> GetTypes(Type type, bool onlyInstantiable) {
    225       return from asm in AppDomain.CurrentDomain.GetAssemblies()
    226              from t in GetTypes(type, asm, onlyInstantiable)
    227              select t;
    228     }
    229 
    230     internal static IEnumerable<Type> GetTypes(IEnumerable<Type> types, bool onlyInstantiable, bool assignableToAllTypes) {
    231       IEnumerable<Type> result = GetTypes(types.First(), onlyInstantiable);
    232       foreach (Type type in types.Skip(1)) {
    233         IEnumerable<Type> discoveredTypes = GetTypes(type, onlyInstantiable);
    234         if (assignableToAllTypes) result = result.Intersect(discoveredTypes);
    235         else result = result.Union(discoveredTypes);
    236       }
    237       return result;
    238     }
    239 
    240     /// <summary>
    241     /// Finds all types that are subtypes or equal to the specified type if they are part of the given
    242     /// <paramref name="pluginDescription"/>.
    243     /// </summary>
    244     /// <param name="type">Most general type for which to find matching types.</param>
    245     /// <param name="pluginDescription">The plugin the subtypes must be part of.</param>
    246     /// <param name="onlyInstantiable">Return only types that are instantiable
    247     /// (interfaces, abstract classes... are not returned)</param>
    248     /// <returns>Enumerable of the discovered types.</returns>
    249     internal static IEnumerable<Type> GetTypes(Type type, IPluginDescription pluginDescription, bool onlyInstantiable) {
    250       PluginDescription pluginDesc = (PluginDescription)pluginDescription;
    251       return from asm in AppDomain.CurrentDomain.GetAssemblies()
    252              where !IsDynamicAssembly(asm)
    253              where pluginDesc.AssemblyLocations.Any(location => location.Equals(Path.GetFullPath(asm.Location), StringComparison.CurrentCultureIgnoreCase))
    254              from t in GetTypes(type, asm, onlyInstantiable)
    255              select t;
    256     }
    257 
    258     internal static IEnumerable<Type> GetTypes(IEnumerable<Type> types, IPluginDescription pluginDescription, bool onlyInstantiable, bool assignableToAllTypes) {
    259       IEnumerable<Type> result = GetTypes(types.First(), pluginDescription, onlyInstantiable);
    260       foreach (Type type in types.Skip(1)) {
    261         IEnumerable<Type> discoveredTypes = GetTypes(type, pluginDescription, onlyInstantiable);
    262         if (assignableToAllTypes) result = result.Intersect(discoveredTypes);
    263         else result = result.Union(discoveredTypes);
    264       }
    265       return result;
    266     }
    267 
    268     private static bool IsDynamicAssembly(Assembly asm) {
    269       return (asm is System.Reflection.Emit.AssemblyBuilder) || string.IsNullOrEmpty(asm.Location);
    270     }
    271 
    272     /// <summary>
    273     /// Gets types that are assignable (same of subtype) to the specified type only from the given assembly.
    274     /// </summary>
    275     /// <param name="type">Most general type we want to find.</param>
    276     /// <param name="assembly">Assembly that should be searched for types.</param>
    277     /// <param name="onlyInstantiable">Return only types that are instantiable
    278     /// (interfaces, abstract classes...  are not returned)</param>
    279     /// <returns>Enumerable of the discovered types.</returns>
    280     private static IEnumerable<Type> GetTypes(Type type, Assembly assembly, bool onlyInstantiable) {
    281       return from t in assembly.GetTypes()
    282              where CheckTypeCompatibility(type, t)
    283              where onlyInstantiable == false ||
    284                 (!t.IsAbstract && !t.IsInterface && !t.HasElementType)
    285              where !IsNonDiscoverableType(t)
    286              select BuildType(t, type);
    287     }
    288 
    289     private static bool IsNonDiscoverableType(Type t) {
    290       return t.GetCustomAttributes(typeof(NonDiscoverableTypeAttribute), false).Any();
    291     }
    292 
    293     private static bool CheckTypeCompatibility(Type type, Type other) {
    294       if (type.IsAssignableFrom(other))
    295         return true;
    296       if (type.IsGenericType && other.IsGenericType) {
    297         try {
    298           if (type.IsAssignableFrom(other.GetGenericTypeDefinition().MakeGenericType(type.GetGenericArguments())))
    299             return true;
    300         }
    301         catch (Exception) { }
    302       }
    303       return false;
    304     }
    305     private static Type BuildType(Type type, Type protoType) {
    306       if (type.IsGenericType && protoType.IsGenericType)
    307         return type.GetGenericTypeDefinition().MakeGenericType(protoType.GetGenericArguments());
    308       else
    309         return type;
    310     }
    311 
    312     private void OnPluginLoaded(PluginInfrastructureEventArgs e) {
    313       if (PluginLoaded != null) PluginLoaded(this, e);
    314     }
    315 
    316     private void OnPluginUnloaded(PluginInfrastructureEventArgs e) {
    317       if (PluginUnloaded != null) PluginUnloaded(this, e);
    318     }
    319 
    320     // infinite lease time
     42    /// infinite lease time
    32143    /// <summary>
    32244    /// Initializes the life time service with infinite lease time.
     
    32648      return null;
    32749    }
    328 
    329     #region IApplicationManager Members
    330 
    331     IEnumerable<T> IApplicationManager.GetInstances<T>() {
    332       return GetInstances<T>();
    333     }
    334 
    335     IEnumerable<object> IApplicationManager.GetInstances(Type type) {
    336       return GetInstances(type);
    337     }
    338 
    339     IEnumerable<Type> IApplicationManager.GetTypes(Type type, bool onlyInstantiable) {
    340       return GetTypes(type, onlyInstantiable);
    341     }
    342     IEnumerable<Type> IApplicationManager.GetTypes(IEnumerable<Type> types, bool onlyInstantiable, bool assignableToAllTypes) {
    343       return GetTypes(types, onlyInstantiable, assignableToAllTypes);
    344     }
    345 
    346     IEnumerable<Type> IApplicationManager.GetTypes(Type type, IPluginDescription plugin, bool onlyInstantiable) {
    347       return GetTypes(type, plugin, onlyInstantiable);
    348     }
    349     IEnumerable<Type> IApplicationManager.GetTypes(IEnumerable<Type> types, IPluginDescription plugin, bool onlyInstantiable, bool assignableToAllTypes) {
    350       return GetTypes(types, plugin, onlyInstantiable, assignableToAllTypes);
    351     }
    352 
    353 
    354     /// <summary>
    355     /// Finds the plugin that declares the <paramref name="type">type</paramref>.
    356     /// </summary>
    357     /// <param name="type">The type of interest.</param>
    358     /// <returns>The description of the plugin that declares the given type or null if the type has not been declared by a known plugin.</returns>
    359     public IPluginDescription GetDeclaringPlugin(Type type) {
    360       if (type == null) throw new ArgumentNullException("type");
    361       foreach (PluginDescription info in Plugins) {
    362         if (info.AssemblyLocations.Contains(Path.GetFullPath(type.Assembly.Location))) return info;
    363       }
    364       return null;
    365     }
    366     #endregion
    36750  }
    36851}
Note: See TracChangeset for help on using the changeset viewer.