Free cookie consent management tool by TermsFeed Policy Generator

source: branches/OaaS/HeuristicLab.PluginInfrastructure/3.3/WebApplicationManager.cs @ 15049

Last change on this file since 15049 was 9363, checked in by spimming, 12 years ago

#1888:

  • Merged revisions from trunk
File size: 28.0 KB
RevLine 
[8506]1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2012 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.IO;
25using System.Linq;
26using System.Reflection;
[9363]27using System.Text;
[8506]28using HeuristicLab.PluginInfrastructure.Manager;
29
30namespace HeuristicLab.PluginInfrastructure {
31
32  /// <summary>
33  /// The SandboxApplicationManager provides properties to retrieve the list of available plugins and applications.
34  /// It also provides methods for type discovery and instantiation for types declared in plugins.
35  /// The SandboxApplicationManager is used in sandboxed Application Domains where permissions are restricted and
36  /// only partially-trusted code can be executed.
37  /// </summary>
38  internal class WebApplicationManager : MarshalByRefObject, IApplicationManager {
39    // private class to store plugin dependency declarations while reflecting over plugins
[9363]40    private class PluginDependency {
[8506]41      public string Name { get; private set; }
42      public Version Version { get; private set; }
43
[9363]44      public PluginDependency(string name, Version version) {
[8506]45        this.Name = name;
46        this.Version = version;
47      }
48    }
49
50    /// <summary>
51    /// Fired when a plugin is loaded.
52    /// </summary>
53    internal event EventHandler<PluginInfrastructureEventArgs> PluginLoaded;
54    /// <summary>
55    /// Fired when a plugin is unloaded (when the application terminates).
56    /// </summary>
57    internal event EventHandler<PluginInfrastructureEventArgs> PluginUnloaded;
58
59    // cache for the AssemblyResolveEvent
60    // which must be handled when assemblies are loaded dynamically after the application start
61    protected internal Dictionary<string, Assembly> loadedAssemblies;
62
63    private List<IPlugin> loadedPlugins;
64
65    private List<PluginDescription> plugins;
66    /// <summary>
67    /// Gets all plugins.
68    /// </summary>
69    public IEnumerable<IPluginDescription> Plugins {
70      get { return plugins.Cast<IPluginDescription>(); }
71    }
72
73    private List<ApplicationDescription> applications;
74    /// <summary>
75    /// Gets all installed applications.
76    /// </summary>
77    public IEnumerable<IApplicationDescription> Applications {
78      get { return applications.Cast<IApplicationDescription>(); }
79    }
80
81    internal WebApplicationManager()
82      : base() {
83      loadedAssemblies = new Dictionary<string, Assembly>();
84      loadedPlugins = new List<IPlugin>();
85      plugins = GatherPluginDescriptions();
86    }
87
[8958]88    static private string AssemblyDirectory {
89      get {
90        string codeBase = Assembly.GetExecutingAssembly().CodeBase;
91        UriBuilder uri = new UriBuilder(codeBase);
92        string path = Uri.UnescapeDataString(uri.Path);
93        return Path.GetDirectoryName(path);
94      }
95    }
[8506]96    // find all types implementing IPlugin in the reflectionOnlyAssemblies and create a list of plugin descriptions
97    // the dependencies in the plugin descriptions are not yet set correctly because we need to create
98    // the full list of all plugin descriptions first
[9363]99    private List<PluginDescription> GatherPluginDescriptions() {
[8958]100      /*List<PluginDescription> pluginDescriptions = new List<PluginDescription>();
101
102      // load all assemblies that are available in the project folders
103      var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies().ToList();
104      IList<string> loadedPaths = new List<string>();
105      foreach (var asm in loadedAssemblies) {
106        try {
107          loadedPaths.Add(asm.Location);
108        }
109        catch (Exception ex) {
110        }
111      }*/
112      /*var assembliePaths = from location in loadedAssemblies                           
113                           select location.Location;
114
115      var loadedPaths = loadedAssemblies.Select(a => a.Location).ToArray();*/
116      var pv = new PluginValidator() { PluginDir = AssemblyDirectory };
117      pv.DiscoverAndCheckPlugins();
118      return pv.Plugins.ToList();
119      /*var pluginManager = new PluginManager(AssemblyDirectory);
120      pluginManager.DiscoverAndCheckPlugins();
121      return pluginManager.Plugins.ToList();*/
122
123      /*var referencedPaths = Directory.GetFiles(AssemblyDirectory, "*.dll");
124      var toLoad = referencedPaths.Where(r => !loadedPaths.Contains(r, StringComparer.InvariantCultureIgnoreCase)).ToList();
125      toLoad.ForEach(path => loadedAssemblies.Add(AppDomain.CurrentDomain.Load(AssemblyName.GetAssemblyName(path))));
126     
127      foreach (Assembly assembly in loadedAssemblies)
[8506]128      {
129        // GetExportedTypes throws FileNotFoundException when a referenced assembly
130        // of the current assembly is missing.
131        try {
132          // loadedAssemblies.Add(assembly.GetName().Name, assembly);
133          // if there is a type that implements IPlugin
134          // use AssemblyQualifiedName to compare the types because we can't directly
135          // compare ReflectionOnly types and execution types
136          var assemblyPluginDescriptions = from t in assembly.GetExportedTypes()
137                                           where !t.IsAbstract && t.GetInterfaces().Any(x => x.AssemblyQualifiedName == typeof(IPlugin).AssemblyQualifiedName)
138                                           select GetPluginDescription(t);
[8958]139
140          // TODO: Also load all plugin descriptors from assemblies liying in the app domain folder!!!!!
[8506]141          pluginDescriptions.AddRange(assemblyPluginDescriptions);
142        }
143        // ignore exceptions. Just don't yield a plugin description when an exception is thrown
144        catch (NotSupportedException) {
145        }
146        catch (FileNotFoundException) {
147        }
148        catch (FileLoadException) {
149        }
150        catch (InvalidPluginException) {
151        }
152        catch (TypeLoadException) {
153        }
154        catch (MissingMemberException) {
155        }
156      }
[8958]157      return pluginDescriptions;*/
[8506]158    }
159
160    /// <summary>
161    /// Extracts plugin information for this type.
162    /// Reads plugin name, list and type of files and dependencies of the plugin. This information is necessary for
163    /// plugin dependency checking before plugin activation.
164    /// </summary>
165    /// <param name="pluginType"></param>
[9363]166    private PluginDescription GetPluginDescription(Type pluginType) {
[8506]167
168      string pluginName, pluginDescription, pluginVersion;
169      string contactName, contactAddress;
170      GetPluginMetaData(pluginType, out pluginName, out pluginDescription, out pluginVersion);
171      GetPluginContactMetaData(pluginType, out contactName, out contactAddress);
172      var pluginFiles = GetPluginFilesMetaData(pluginType);
173      var pluginDependencies = GetPluginDependencyMetaData(pluginType);
174
175      // minimal sanity check of the attribute values
176      if (!string.IsNullOrEmpty(pluginName) &&
177          pluginFiles.Count() > 0 &&                                 // at least one file
[9363]178          pluginFiles.Any(f => f.Type == PluginFileType.Assembly)) { // at least one assembly
[8506]179        // create a temporary PluginDescription that contains the attribute values
180        PluginDescription info = new PluginDescription();
181        info.Name = pluginName;
182        info.Description = pluginDescription;
183        info.Version = new Version(pluginVersion);
184        info.ContactName = contactName;
185        info.ContactEmail = contactAddress;
186        info.LicenseText = ReadLicenseFiles(pluginFiles);
187        info.AddFiles(pluginFiles);
188
189        //this.pluginDependencies[info] = pluginDependencies;
190        return info;
[9363]191      } else {
[8506]192        throw new InvalidPluginException("Invalid metadata in plugin " + pluginType.ToString());
193      }
194    }
195
[9363]196    private static string ReadLicenseFiles(IEnumerable<PluginFile> pluginFiles) {
[8506]197      // combine the contents of all plugin files
198      var licenseFiles = from file in pluginFiles
199                         where file.Type == PluginFileType.License
200                         select file;
201      if (licenseFiles.Count() == 0) return string.Empty;
202      StringBuilder licenseTextBuilder = new StringBuilder();
203      licenseTextBuilder.AppendLine(File.ReadAllText(licenseFiles.First().Name));
[9363]204      foreach (var licenseFile in licenseFiles.Skip(1)) {
[8506]205        licenseTextBuilder.AppendLine().AppendLine(); // leave some empty space between multiple license files
206        licenseTextBuilder.AppendLine(File.ReadAllText(licenseFile.Name));
207      }
208      return licenseTextBuilder.ToString();
209    }
210
[9363]211    private static IEnumerable<PluginDependency> GetPluginDependencyMetaData(Type pluginType) {
[8506]212      // get all attributes of type PluginDependency
213      var dependencyAttributes = from attr in CustomAttributeData.GetCustomAttributes(pluginType)
214                                 where IsAttributeDataForType(attr, typeof(PluginDependencyAttribute))
215                                 select attr;
216
[9363]217      foreach (var dependencyAttr in dependencyAttributes) {
[8506]218        string name = (string)dependencyAttr.ConstructorArguments[0].Value;
219        Version version = new Version("0.0.0.0"); // default version
220        // check if version is given for now
221        // later when the constructor of PluginDependencyAttribute with only one argument has been removed
222        // this conditional can be removed as well
[9363]223        if (dependencyAttr.ConstructorArguments.Count > 1) {
224          try {
[8506]225            version = new Version((string)dependencyAttr.ConstructorArguments[1].Value); // might throw FormatException
226          }
[9363]227          catch (FormatException ex) {
[8506]228            throw new InvalidPluginException("Invalid version format of dependency " + name + " in plugin " + pluginType.ToString(), ex);
229          }
230        }
231        yield return new PluginDependency(name, version);
232      }
233    }
234
[9363]235    private static bool IsAttributeDataForType(CustomAttributeData attributeData, Type attributeType) {
[8506]236      return attributeData.Constructor.DeclaringType.AssemblyQualifiedName == attributeType.AssemblyQualifiedName;
237    }
238
[9363]239    private static void GetPluginContactMetaData(Type pluginType, out string contactName, out string contactAddress) {
[8506]240      // get attribute of type ContactInformation if there is any
241      var contactInfoAttribute = (from attr in CustomAttributeData.GetCustomAttributes(pluginType)
242                                  where IsAttributeDataForType(attr, typeof(ContactInformationAttribute))
243                                  select attr).SingleOrDefault();
244
[9363]245      if (contactInfoAttribute != null) {
[8506]246        contactName = (string)contactInfoAttribute.ConstructorArguments[0].Value;
247        contactAddress = (string)contactInfoAttribute.ConstructorArguments[1].Value;
[9363]248      } else {
[8506]249        contactName = string.Empty;
250        contactAddress = string.Empty;
251      }
252    }
253
254    // not static because we need the PluginDir property
[9363]255    private IEnumerable<PluginFile> GetPluginFilesMetaData(Type pluginType) {
[8506]256      // get all attributes of type PluginFileAttribute
257      var pluginFileAttributes = from attr in CustomAttributeData.GetCustomAttributes(pluginType)
258                                 where IsAttributeDataForType(attr, typeof(PluginFileAttribute))
259                                 select attr;
[9363]260      foreach (var pluginFileAttribute in pluginFileAttributes) {
[8506]261        string pluginFileName = (string)pluginFileAttribute.ConstructorArguments[0].Value;
262        PluginFileType fileType = (PluginFileType)pluginFileAttribute.ConstructorArguments[1].Value;
263        yield return new PluginFile(Path.GetFullPath(Path.Combine(@"C:\dev\Heuristiclab\branches\OaaS\bin", pluginFileName)), fileType);
264      }
265    }
266
[9363]267    private static void GetPluginMetaData(Type pluginType, out string pluginName, out string pluginDescription, out string pluginVersion) {
[8506]268      // there must be a single attribute of type PluginAttribute
269      var pluginMetaDataAttr = (from attr in CustomAttributeData.GetCustomAttributes(pluginType)
270                                where IsAttributeDataForType(attr, typeof(PluginAttribute))
271                                select attr).Single();
272
273      pluginName = (string)pluginMetaDataAttr.ConstructorArguments[0].Value;
274
275      // default description and version
276      pluginVersion = "0.0.0.0";
277      pluginDescription = string.Empty;
[9363]278      if (pluginMetaDataAttr.ConstructorArguments.Count() == 2) {
[8506]279        // if two arguments are given the second argument is the version
280        pluginVersion = (string)pluginMetaDataAttr.ConstructorArguments[1].Value;
[9363]281      } else if (pluginMetaDataAttr.ConstructorArguments.Count() == 3) {
[8506]282        // if three arguments are given the second argument is the description and the third is the version
283        pluginDescription = (string)pluginMetaDataAttr.ConstructorArguments[1].Value;
284        pluginVersion = (string)pluginMetaDataAttr.ConstructorArguments[2].Value;
285      }
286    }
287
288    /// <summary>
289    /// Prepares the application domain for the execution of an HL application.
290    /// Pre-loads all <paramref name="plugins"/>.
291    /// </summary>
292    /// <param name="apps">Enumerable of available HL applications.</param>
293    /// <param name="plugins">Enumerable of plugins that should be pre-loaded.</param> 
294    internal void PrepareApplicationDomain(IEnumerable<ApplicationDescription> apps, IEnumerable<PluginDescription> plugins) {
295      this.plugins = new List<PluginDescription>(plugins);
296      this.applications = new List<ApplicationDescription>(apps);
297      ApplicationManager.RegisterApplicationManager(this);
298      LoadPlugins(plugins);
299    }
300
301    /// <summary>
302    /// Loads the <paramref name="plugins"/> into this application domain.
303    /// </summary>
304    /// <param name="plugins">Enumerable of plugins that should be loaded.</param>
305    private void LoadPlugins(IEnumerable<PluginDescription> plugins) {
306      // load all loadable plugins (all dependencies available) into the execution context
307      foreach (var desc in PluginDescriptionIterator.IterateDependenciesBottomUp(plugins.Where(x => x.PluginState != PluginState.Disabled))) {
308        foreach (string fileName in desc.AssemblyLocations) {
309          // load assembly reflection only first to get the full assembly name
310          var reflectionOnlyAssembly = Assembly.ReflectionOnlyLoadFrom(fileName);
311          // load the assembly into execution context using full assembly name
312          var asm = Assembly.Load(reflectionOnlyAssembly.FullName);
313          RegisterLoadedAssembly(asm);
314          // instantiate and load all plugins in this assembly
315          foreach (var plugin in GetInstances<IPlugin>(asm)) {
316            plugin.OnLoad();
317            loadedPlugins.Add(plugin);
318          }
319        }
320        OnPluginLoaded(new PluginInfrastructureEventArgs(desc));
321        desc.Load();
322      }
323    }
324
325    /// <summary>
326    /// Runs the application declared in <paramref name="appInfo"/>.
327    /// This is a synchronous call. When the application is terminated all plugins are unloaded.
328    /// </summary>
329    /// <param name="appInfo">Description of the application to run</param>
[9363]330    internal void Run(ApplicationDescription appInfo, ICommandLineArgument[] args) {
[8506]331      IApplication runnablePlugin = (IApplication)Activator.CreateInstance(appInfo.DeclaringAssemblyName, appInfo.DeclaringTypeName).Unwrap();
332      try {
[9363]333        runnablePlugin.Run(args);
[8506]334      }
335      finally {
336        // unload plugins in reverse order
337        foreach (var plugin in loadedPlugins.Reverse<IPlugin>()) {
338          plugin.OnUnload();
339        }
340        foreach (var desc in PluginDescriptionIterator.IterateDependenciesBottomUp(plugins.Where(x => x.PluginState != PluginState.Disabled))) {
341          desc.Unload();
342          OnPluginUnloaded(new PluginInfrastructureEventArgs(desc));
343        }
344      }
345    }
346
347    // register assembly in the assembly cache for the AssemblyResolveEvent
348    private void RegisterLoadedAssembly(Assembly asm) {
349      if (loadedAssemblies.ContainsKey(asm.FullName) || loadedAssemblies.ContainsKey(asm.GetName().Name)) {
350        throw new ArgumentException("An assembly with the name " + asm.GetName().Name + " has been registered already.", "asm");
351      }
352      loadedAssemblies.Add(asm.FullName, asm);
353      loadedAssemblies.Add(asm.GetName().Name, asm); // add short name
354    }
355
356    /// <summary>
357    /// Creates an instance of all types that are subtypes or the same type of the specified type and declared in <paramref name="plugin"/>
358    /// </summary>
359    /// <typeparam name="T">Most general type.</typeparam>
360    /// <returns>Enumerable of the created instances.</returns>
361    internal static IEnumerable<T> GetInstances<T>(IPluginDescription plugin) where T : class {
362      List<T> instances = new List<T>();
363      foreach (Type t in GetTypes(typeof(T), plugin, onlyInstantiable: true, includeGenericTypeDefinitions: false)) {
364        T instance = null;
365        try { instance = (T)Activator.CreateInstance(t); }
366        catch { }
367        if (instance != null) instances.Add(instance);
368      }
369      return instances;
370    }
371    /// <summary>
372    /// 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"/>.
373    /// </summary>
374    /// <typeparam name="T">Most general type.</typeparam>
375    /// <param name="asm">Declaring assembly.</param>
376    /// <returns>Enumerable of the created instances.</returns>
377    private static IEnumerable<T> GetInstances<T>(Assembly asm) where T : class {
378      List<T> instances = new List<T>();
379      foreach (Type t in GetTypes(typeof(T), asm, onlyInstantiable: true, includeGenericTypeDefinitions: false)) {
380        T instance = null;
381        try { instance = (T)Activator.CreateInstance(t); }
382        catch { }
383        if (instance != null) instances.Add(instance);
384      }
385      return instances;
386    }
387    /// <summary>
388    /// Creates an instance of all types that are subtypes or the same type of the specified type
389    /// </summary>
390    /// <typeparam name="T">Most general type.</typeparam>
391    /// <returns>Enumerable of the created instances.</returns>
392    internal static IEnumerable<T> GetInstances<T>() where T : class {
393      return from i in GetInstances(typeof(T))
394             select (T)i;
395    }
396
397    /// <summary>
398    /// Creates an instance of all types that are subtypes or the same type of the specified type
399    /// </summary>
400    /// <param name="type">Most general type.</param>
401    /// <returns>Enumerable of the created instances.</returns>
402    internal static IEnumerable<object> GetInstances(Type type) {
403      List<object> instances = new List<object>();
404      foreach (Type t in GetTypes(type, onlyInstantiable: true, includeGenericTypeDefinitions: false)) {
405        object instance = null;
406        try { instance = Activator.CreateInstance(t); }
407        catch { }
408        if (instance != null) instances.Add(instance);
409      }
410      return instances;
411    }
412
413    /// <summary>
414    /// Finds all types that are subtypes or equal to the specified type.
415    /// </summary>
416    /// <param name="type">Most general type for which to find matching types.</param>
417    /// <param name="onlyInstantiable">Return only types that are instantiable
418    /// <param name="includeGenericTypeDefinitions">Specifies if generic type definitions shall be included</param>
419    /// (interfaces, abstract classes... are not returned)</param>
420    /// <returns>Enumerable of the discovered types.</returns>
421    internal static IEnumerable<Type> GetTypes(Type type, bool onlyInstantiable, bool includeGenericTypeDefinitions) {
422      return from asm in AppDomain.CurrentDomain.GetAssemblies()
423             from t in GetTypes(type, asm, onlyInstantiable, includeGenericTypeDefinitions)
424             select t;
425    }
426
427    internal static IEnumerable<Type> GetTypes(IEnumerable<Type> types, bool onlyInstantiable, bool includeGenericTypeDefinitions, bool assignableToAllTypes) {
428      IEnumerable<Type> result = GetTypes(types.First(), onlyInstantiable, includeGenericTypeDefinitions);
429      foreach (Type type in types.Skip(1)) {
430        IEnumerable<Type> discoveredTypes = GetTypes(type, onlyInstantiable, includeGenericTypeDefinitions);
431        if (assignableToAllTypes) result = result.Intersect(discoveredTypes);
432        else result = result.Union(discoveredTypes);
433      }
434      return result;
435    }
436
437    /// <summary>
438    /// Finds all types that are subtypes or equal to the specified type if they are part of the given
439    /// <paramref name="pluginDescription"/>.
440    /// </summary>
441    /// <param name="type">Most general type for which to find matching types.</param>
442    /// <param name="pluginDescription">The plugin the subtypes must be part of.</param>
443    /// <param name="onlyInstantiable">Return only types that are instantiable
444    /// <param name="includeGenericTypeDefinitions">Specifies if generic type definitions shall be included</param>
445    /// (interfaces, abstract classes... are not returned)</param>
446    /// <returns>Enumerable of the discovered types.</returns>
447    internal static IEnumerable<Type> GetTypes(Type type, IPluginDescription pluginDescription, bool onlyInstantiable, bool includeGenericTypeDefinitions) {
448      PluginDescription pluginDesc = (PluginDescription)pluginDescription;
449      return from asm in AppDomain.CurrentDomain.GetAssemblies()
450             where !asm.IsDynamic && !string.IsNullOrEmpty(asm.Location)
451             where pluginDesc.AssemblyLocations.Any(location => location.Equals(Path.GetFullPath(asm.Location), StringComparison.CurrentCultureIgnoreCase))
452             from t in GetTypes(type, asm, onlyInstantiable, includeGenericTypeDefinitions)
453             select t;
454    }
455
456    internal static IEnumerable<Type> GetTypes(IEnumerable<Type> types, IPluginDescription pluginDescription, bool onlyInstantiable, bool includeGenericTypeDefinitions, bool assignableToAllTypes) {
457      IEnumerable<Type> result = GetTypes(types.First(), pluginDescription, onlyInstantiable, includeGenericTypeDefinitions);
458      foreach (Type type in types.Skip(1)) {
459        IEnumerable<Type> discoveredTypes = GetTypes(type, pluginDescription, onlyInstantiable, includeGenericTypeDefinitions);
460        if (assignableToAllTypes) result = result.Intersect(discoveredTypes);
461        else result = result.Union(discoveredTypes);
462      }
463      return result;
464    }
465
466    /// <summary>
467    /// Gets types that are assignable (same of subtype) to the specified type only from the given assembly.
468    /// </summary>
469    /// <param name="type">Most general type we want to find.</param>
470    /// <param name="assembly">Assembly that should be searched for types.</param>
471    /// <param name="onlyInstantiable">Return only types that are instantiable
472    /// (interfaces, abstract classes...  are not returned)</param>
473    /// <param name="includeGenericTypeDefinitions">Specifies if generic type definitions shall be included</param>
474    /// <returns>Enumerable of the discovered types.</returns>
475    private static IEnumerable<Type> GetTypes(Type type, Assembly assembly, bool onlyInstantiable, bool includeGenericTypeDefinitions) {
476      var buildTypes = from t in assembly.GetTypes()
477                       where CheckTypeCompatibility(type, t)
478                       where !IsNonDiscoverableType(t)
479                       where onlyInstantiable == false ||
480                             (!t.IsAbstract && !t.IsInterface && !t.HasElementType)
481                       select BuildType(t, type);
482
483      return from t in buildTypes
484             where includeGenericTypeDefinitions || !t.IsGenericTypeDefinition
485             select t;
486    }
487
488
489    private static bool IsNonDiscoverableType(Type t) {
490      return t.GetCustomAttributes(typeof(NonDiscoverableTypeAttribute), false).Any();
491    }
492
493    private static bool CheckTypeCompatibility(Type type, Type other) {
494      if (type.IsAssignableFrom(other))
495        return true;
496      if (type.IsGenericType && other.IsGenericType) {
497        var otherGenericArguments = other.GetGenericArguments();
498        var typeGenericArguments = type.GetGenericArguments();
499
500        //check type arguments count
501        if (otherGenericArguments.Length != typeGenericArguments.Length)
502          return false;
503
504        //check type arguments & constraints
505        int i = 0;
506        foreach (var genericArgument in typeGenericArguments) {
507          if (otherGenericArguments[i].IsGenericParameter) {
508            foreach (var constraint in otherGenericArguments[i].GetGenericParameterConstraints())
509              if (!constraint.IsAssignableFrom(genericArgument)) return false;
510          } else if (genericArgument != otherGenericArguments[i]) return false;
511          i++;
512        }
513        //check types
514        try {
515          var otherGenericTypeDefinition = other.GetGenericTypeDefinition();
516          if (type.IsAssignableFrom(otherGenericTypeDefinition.MakeGenericType(typeGenericArguments)))
517            return true;
518        }
519        catch (Exception) { }
520      }
521      return false;
522    }
523    private static Type BuildType(Type type, Type protoType) {
524      if (type.IsGenericType && protoType.IsGenericType)
525        return type.GetGenericTypeDefinition().MakeGenericType(protoType.GetGenericArguments());
526      else
527        return type;
528    }
529
530    private void OnPluginLoaded(PluginInfrastructureEventArgs e) {
531      if (PluginLoaded != null) PluginLoaded(this, e);
532    }
533
534    private void OnPluginUnloaded(PluginInfrastructureEventArgs e) {
535      if (PluginUnloaded != null) PluginUnloaded(this, e);
536    }
537
538    #region IApplicationManager Members
539
540    IEnumerable<T> IApplicationManager.GetInstances<T>() {
541      return GetInstances<T>();
542    }
543
544    IEnumerable<object> IApplicationManager.GetInstances(Type type) {
545      return GetInstances(type);
546    }
547
548    IEnumerable<Type> IApplicationManager.GetTypes(Type type, bool onlyInstantiable, bool includeGenericTypeDefinitions) {
549      return GetTypes(type, onlyInstantiable, includeGenericTypeDefinitions);
550    }
551    IEnumerable<Type> IApplicationManager.GetTypes(IEnumerable<Type> types, bool onlyInstantiable, bool includeGenericTypeDefinitions, bool assignableToAllTypes) {
552      return GetTypes(types, onlyInstantiable, includeGenericTypeDefinitions, assignableToAllTypes);
553    }
554
555    IEnumerable<Type> IApplicationManager.GetTypes(Type type, IPluginDescription plugin, bool onlyInstantiable, bool includeGenericTypeDefinitions) {
556      return GetTypes(type, plugin, onlyInstantiable, includeGenericTypeDefinitions);
557    }
558    IEnumerable<Type> IApplicationManager.GetTypes(IEnumerable<Type> types, IPluginDescription plugin, bool onlyInstantiable, bool includeGenericTypeDefinitions, bool assignableToAllTypes) {
559      return GetTypes(types, plugin, onlyInstantiable, includeGenericTypeDefinitions, assignableToAllTypes);
560    }
561
562    /// <summary>
563    /// Finds the plugin that declares the <paramref name="type">type</paramref>.
564    /// </summary>
565    /// <param name="type">The type of interest.</param>
566    /// <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>
567    public IPluginDescription GetDeclaringPlugin(Type type) {
568      if (type == null) throw new ArgumentNullException("type");
569      var name = type.Assembly.GetName().Name;
570      foreach (PluginDescription info in Plugins) {
571        var f = Path.GetFileNameWithoutExtension(info.Files.ElementAt(0).Name);
572        if (f.Contains(name)) return info;
573      }
574      return null;
575    }
576    #endregion
577  }
578}
Note: See TracBrowser for help on using the repository browser.