Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 9283 was 8958, checked in by fschoepp, 12 years ago

#1888:

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