Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
11/11/09 18:25:15 (14 years ago)
Author:
gkronber
Message:

Refactored class Loader in plugin infrastructure. #799

Location:
branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure.Manager
Files:
1 edited
1 moved

Legend:

Unmodified
Added
Removed
  • branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure.Manager

    • Property svn:ignore
      •  

        old new  
        11bin
        22obj
         3HeuristicLab.PluginInfrastructure.Manager.csproj.user
  • branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure.Manager/Loader.cs

    r2475 r2481  
    2626using System.IO;
    2727using System.Diagnostics;
    28 using System.Windows.Forms;
    29 
    30 namespace HeuristicLab.PluginInfrastructure {
     28using System.Linq;
     29
     30
     31namespace HeuristicLab.PluginInfrastructure.Manager {
    3132  internal class Loader : MarshalByRefObject {
    32     /// <summary>
    33     /// Event handler for loaded plugins.
    34     /// </summary>
    35     /// <param name="pluginName">The plugin that has been loaded.</param>
    36     public delegate void PluginLoadedEventHandler(string pluginName);
    37 
    38     public delegate void PluginLoadFailedEventHandler(string pluginName, string args);
    39 
    40     private Dictionary<PluginInfo, List<string>> pluginDependencies = new Dictionary<PluginInfo, List<string>>();
    41     private List<PluginInfo> preloadedPluginInfos = new List<PluginInfo>();
    42     private Dictionary<IPlugin, PluginInfo> pluginInfos = new Dictionary<IPlugin, PluginInfo>();
    43     private Dictionary<PluginInfo, IPlugin> allPlugins = new Dictionary<PluginInfo, IPlugin>();
    44     private List<PluginInfo> disabledPlugins = new List<PluginInfo>();
    45     private string pluginDir = Application.StartupPath + "/" + HeuristicLab.PluginInfrastructure.Properties.Settings.Default.PluginDir;
    46 
    47     internal event PluginLoadFailedEventHandler MissingPluginFile;
    4833    internal event PluginManagerActionEventHandler PluginAction;
    4934
    50     internal ICollection<PluginInfo> ActivePlugins {
    51       get {
    52         List<PluginInfo> list = new List<PluginInfo>();
    53         foreach (PluginInfo info in allPlugins.Keys) {
    54           if (!disabledPlugins.Exists(delegate(PluginInfo disabledInfo) { return info.Name == disabledInfo.Name; })) {
    55             list.Add(info);
    56           }
    57         }
    58         return list;
    59       }
    60     }
    61 
    62     internal ICollection<PluginInfo> InstalledPlugins {
    63       get {
    64         return new List<PluginInfo>(allPlugins.Keys);
    65       }
    66     }
    67 
    68     internal ICollection<PluginInfo> DisabledPlugins {
    69       get {
    70         return disabledPlugins;
    71       }
    72     }
    73 
    74     private ICollection<ApplicationInfo> applications;
    75     internal ICollection<ApplicationInfo> InstalledApplications {
     35    private Dictionary<PluginDescription, List<string>> pluginDependencies;
     36
     37    private List<ApplicationDescription> applications;
     38    internal IEnumerable<ApplicationDescription> Applications {
    7639      get {
    7740        return applications;
     
    7942    }
    8043
    81     private IPlugin FindPlugin(PluginInfo plugin) {
    82       if (allPlugins.ContainsKey(plugin)) {
    83         return allPlugins[plugin];
    84       } else return null;
     44    private IEnumerable<PluginDescription> plugins;
     45    internal IEnumerable<PluginDescription> Plugins {
     46      get {
     47        return plugins;
     48      }
     49    }
     50
     51    public string PluginDir { get; set; }
     52
     53    public Loader() {
     54      this.applications = new List<ApplicationDescription>();
     55      this.plugins = new List<PluginDescription>();
     56      this.pluginDependencies = new Dictionary<PluginDescription, List<string>>();
    8557    }
    8658
     
    8961    /// Init first clears all internal datastructures (including plugin lists)
    9062    /// 1. All assemblies in the plugins directory are loaded into the reflection only context.
    91     /// 2. The loader checks if all dependencies for each assembly are available.
    92     /// 3. All assemblies for which there are no dependencies missing are loaded into the execution context.
    93     /// 4. Each loaded assembly is searched for a type that implements IPlugin, then one instance of each IPlugin type is activated
    94     /// 5. The loader checks if all necessary files for each plugin are available.
    95     /// 6. The loader builds an acyclic graph of PluginDescriptions (childs are dependencies of a plugin) based on the
    96     /// list of assemblies of an plugin and the list of dependencies for each of those assemblies
     63    /// 2. The loader checks if all necessary files for each plugin are available.
     64    /// 3. The loaded builds the tree of plugin descriptions (dependencies)
     65    /// 4. The loader checks if all dependencies for each plugin are ok.
     66    /// 5. All plugins for which there are no dependencies missing are loaded into the execution context.
     67    /// 6. Each loaded plugin (all assemblies) is searched for a types that implement IPlugin
     68    ///    then one instance of each IPlugin type is activated and the OnLoad hook is called.
     69    /// 7. All types implementing IApplication are discovered
    9770    /// </summary>
    98     /// <exception cref="FileLoadException">Thrown when the file could not be loaded.</exception>
    9971    internal void Init() {
    100       AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += delegate(object sender, ResolveEventArgs args) {
    101         try {
    102           return Assembly.ReflectionOnlyLoad(args.Name);
    103         }
    104         catch (FileLoadException ex) {
    105           return null;
    106         }
    107       };
    108       allPlugins.Clear();
    109       disabledPlugins.Clear();
    110       pluginInfos.Clear();
    111       pluginsByName.Clear();
     72      //AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += delegate(object sender, ResolveEventArgs args) {
     73      //  try {
     74      //    return Assembly.ReflectionOnlyLoad(args.Name);
     75      //  }
     76      //  catch (FileLoadException ex) {
     77      //    return null;
     78      //  }
     79      //};
    11280      pluginDependencies.Clear();
    11381
    114       List<Assembly> assemblies = ReflectionOnlyLoadDlls();
    115       CheckAssemblyDependencies(assemblies);
    116       CheckPluginFiles();
    117       CheckPluginDependencies();
    118       LoadPlugins();
    119 
     82      IEnumerable<Assembly> reflectionOnlyAssemblies = ReflectionOnlyLoadDlls();
     83      IEnumerable<PluginDescription> pluginDescriptions = GatherPluginDescriptions(reflectionOnlyAssemblies);
     84      CheckPluginFiles(pluginDescriptions);
     85
     86      // a full list of plugin descriptions is available now we can build the dependency tree
     87      BuildDependencyTree(pluginDescriptions);
     88
     89      // recursively check if all necessary plugins are available and not disabled
     90      // disable plugins with missing or disabled dependencies
     91      CheckPluginDependencies(pluginDescriptions);
     92
     93      // test full loading (in contrast to reflection only loading) of plugins
     94      // disables plugins that are not loaded correctly
     95      LoadPlugins(pluginDescriptions);
     96
     97      plugins = pluginDescriptions;
     98      DiscoverApplications();
     99    }
     100
     101    private void DiscoverApplications() {
    120102      DiscoveryService service = new DiscoveryService();
    121103      IApplication[] apps = service.GetInstances<IApplication>();
    122       applications = new List<ApplicationInfo>();
     104      applications = new List<ApplicationDescription>();
    123105
    124106      foreach (IApplication application in apps) {
    125         ApplicationInfo info = new ApplicationInfo();
     107        ApplicationDescription info = new ApplicationDescription();
    126108        info.Name = application.Name;
    127109        info.Version = application.Version;
     
    135117    }
    136118
    137     private List<Assembly> ReflectionOnlyLoadDlls() {
     119    private IEnumerable<Assembly> ReflectionOnlyLoadDlls() {
    138120      List<Assembly> assemblies = new List<Assembly>();
    139       // load all installed plugins into the reflection only context
    140       foreach (String filename in Directory.GetFiles(pluginDir, "*.dll")) {
     121      // try to load each .dll file in the plugin directory into the reflection only context
     122      foreach (string filename in Directory.GetFiles(PluginDir, "*.dll")) {
    141123        try {
    142           assemblies.Add(ReflectionOnlyLoadDll(filename));
     124          assemblies.Add(Assembly.ReflectionOnlyLoadFrom(filename));
    143125        }
    144126        catch (BadImageFormatException) { } // just ignore the case that the .dll file is not actually a CLR dll
     
    147129    }
    148130
    149     private Assembly ReflectionOnlyLoadDll(string filename) {
    150       return Assembly.ReflectionOnlyLoadFrom(filename);
    151     }
    152 
    153     private void CheckAssemblyDependencies(List<Assembly> assemblies) {
     131    // find all types implementing IPlugin in the reflectionOnlyAssemblies and create a list of plugin descriptions
     132    // the dependencies in the plugin descriptions are not yet set correctly because we need to create
     133    // the full list of all plugin descriptions first
     134    private IEnumerable<PluginDescription> GatherPluginDescriptions(IEnumerable<Assembly> assemblies) {
     135      List<PluginDescription> pluginDescriptions = new List<PluginDescription>();
    154136      foreach (Assembly assembly in assemblies) {
    155137        // GetExportedTypes throws FileNotFoundException when a referenced assembly
    156138        // of the current assembly is missing.
    157139        try {
    158           Type[] exported = assembly.GetExportedTypes();
    159 
    160           foreach (Type t in exported) {
     140          foreach (Type t in assembly.GetExportedTypes()) {
    161141            // if there is a type that implements IPlugin
    162             if (! t.IsAbstract && Array.Exists<Type>(t.GetInterfaces(), delegate(Type iface) {
    163               // use AssemblyQualifiedName to compare the types because we can't directly
    164               // compare ReflectionOnly types and Execution types
    165               return iface.AssemblyQualifiedName == typeof(IPlugin).AssemblyQualifiedName;
    166             })) {
     142            // use AssemblyQualifiedName to compare the types because we can't directly
     143            // compare ReflectionOnly types and Execution types
     144            if (!t.IsAbstract &&
     145                t.GetInterfaces().Any(x => x.AssemblyQualifiedName == typeof(IPlugin).AssemblyQualifiedName)) {
    167146              // fetch the attributes of the IPlugin type
    168               GetPluginAttributeData(t);
     147              pluginDescriptions.Add(GetPluginDescription(t));
    169148            }
    170149          }
    171150        }
    172151        catch (FileNotFoundException ex) {
    173           PluginInfo info = new PluginInfo();
    174           AssemblyName name = assembly.GetName();
    175           info.Name = name.Name;
    176           info.Version = name.Version;
    177           info.Assemblies.Add(assembly.FullName);
    178           info.Files.Add(assembly.Location);
    179           info.Message = "File not found: " + ex.FileName;
    180           disabledPlugins.Add(info);
     152          //PluginDescription info = new PluginDescription();
     153          //AssemblyName name = assembly.GetName();
     154          //info.Name = name.Name;
     155          //info.Version = name.Version;
     156          //info.Assemblies.Add(assembly.FullName);
     157          //info.Files.Add(assembly.Location);
     158          //info.Message = "File not found: " + ex.FileName;
     159          //disabledPlugins.Add(info);
    181160        }
    182161        catch (FileLoadException ex) {
    183           PluginInfo info = new PluginInfo();
    184           AssemblyName name = assembly.GetName();
    185           info.Name = name.Name;
    186           info.Version = name.Version;
    187           info.Files.Add(assembly.Location);
    188           info.Assemblies.Add(assembly.FullName);
    189           info.Message = "Couldn't load file: " + ex.FileName;
    190           disabledPlugins.Add(info);
     162          //PluginDescription info = new PluginDescription();
     163          //AssemblyName name = assembly.GetName();
     164          //info.Name = name.Name;
     165          //info.Version = name.Version;
     166          //info.Files.Add(assembly.Location);
     167          //info.Assemblies.Add(assembly.FullName);
     168          //info.Message = "Couldn't load file: " + ex.FileName;
     169          //disabledPlugins.Add(info);
    191170        }
    192171        catch (InvalidPluginException ex) {
    193           PluginInfo info = new PluginInfo();
    194           AssemblyName name = assembly.GetName();
    195           info.Name = name.Name;
    196           info.Version = name.Version;
    197           info.Files.Add(assembly.Location);
    198           info.Assemblies.Add(assembly.FullName);
    199           info.Message = "Couldn't load plugin class from assembly: " + assembly.GetName().Name+". Necessary plugin attributes are missing.";
    200           disabledPlugins.Add(info);
    201         }
    202       }
     172          //PluginDescription info = new PluginDescription();
     173          //AssemblyName name = assembly.GetName();
     174          //info.Name = name.Name;
     175          //info.Version = name.Version;
     176          //info.Files.Add(assembly.Location);
     177          //info.Assemblies.Add(assembly.FullName);
     178          //info.Message = "Couldn't load plugin class from assembly: " + assembly.GetName().Name + ". Necessary plugin attributes are missing.";
     179          //disabledPlugins.Add(info);
     180        }
     181      }
     182      return pluginDescriptions;
    203183    }
    204184
     
    209189    /// </summary>
    210190    /// <param name="t"></param>
    211     private void GetPluginAttributeData(Type t) {
     191    private PluginDescription GetPluginDescription(Type pluginType) {
    212192      // get all attributes of that type
    213       IList<CustomAttributeData> attributes = CustomAttributeData.GetCustomAttributes(t);
     193      IList<CustomAttributeData> attributes = CustomAttributeData.GetCustomAttributes(pluginType);
    214194      List<string> pluginAssemblies = new List<string>();
    215195      List<string> pluginDependencies = new List<string>();
    216196      List<string> pluginFiles = new List<string>();
    217       string pluginName = "";
    218       // iterate through all custom attributes and search for named arguments that we are interested in
     197      string pluginName = null;
     198      // iterate through all custom attributes and search for attributed that we are interested in
    219199      foreach (CustomAttributeData attributeData in attributes) {
    220         List<CustomAttributeNamedArgument> namedArguments = new List<CustomAttributeNamedArgument>(attributeData.NamedArguments);
    221         // if the current attribute contains a named argument with the name "Name" then extract the plugin name
    222         CustomAttributeNamedArgument pluginNameArgument = namedArguments.Find(delegate(CustomAttributeNamedArgument arg) {
    223           return arg.MemberInfo.Name == "Name";
    224         });
    225         if (pluginNameArgument.MemberInfo != null) {
    226           pluginName = (string)pluginNameArgument.TypedValue.Value;
    227         }
    228         // if the current attribute contains a named argument with the name "Dependency" then extract the dependency
    229         // and store it in the list of all dependencies
    230         CustomAttributeNamedArgument dependencyNameArgument = namedArguments.Find(delegate(CustomAttributeNamedArgument arg) {
    231           return arg.MemberInfo.Name == "Dependency";
    232         });
    233         if (dependencyNameArgument.MemberInfo != null) {
    234           pluginDependencies.Add((string)dependencyNameArgument.TypedValue.Value);
    235         }
    236         // if the current attribute has a named argument "Filename" then find if the argument "Filetype" is also supplied
    237         // and if the filetype is Assembly then store the name of the assembly in the list of assemblies
    238         CustomAttributeNamedArgument filenameArg = namedArguments.Find(delegate(CustomAttributeNamedArgument arg) {
    239           return arg.MemberInfo.Name == "Filename";
    240         });
    241         CustomAttributeNamedArgument filetypeArg = namedArguments.Find(delegate(CustomAttributeNamedArgument arg) {
    242           return arg.MemberInfo.Name == "Filetype";
    243         });
    244         if (filenameArg.MemberInfo != null && filetypeArg.MemberInfo != null) {
    245           pluginFiles.Add(pluginDir + "/" + (string)filenameArg.TypedValue.Value);
    246           if ((PluginFileType)filetypeArg.TypedValue.Value == PluginFileType.Assembly) {
    247             pluginAssemblies.Add(pluginDir + "/" + (string)filenameArg.TypedValue.Value);
     200        if (IsAttributeDataForType(attributeData, typeof(PluginDescriptionAttribute))) {
     201          pluginName = (string)attributeData.ConstructorArguments[0].Value;
     202        } else if (IsAttributeDataForType(attributeData, typeof(PluginDependencyAttribute))) {
     203          pluginDependencies.Add((string)attributeData.ConstructorArguments[0].Value);
     204        } else if (IsAttributeDataForType(attributeData, typeof(PluginFileAttribute))) {
     205          string pluginFileName = (string)attributeData.ConstructorArguments[0].Value;
     206          PluginFileType fileType = (PluginFileType)attributeData.ConstructorArguments[1].Value;
     207          pluginFiles.Add(PluginDir + "/" + pluginFileName);
     208          if (fileType == PluginFileType.Assembly) {
     209            pluginAssemblies.Add(PluginDir + "/" + pluginFileName);
    248210          }
    249211        }
     
    251213
    252214      // minimal sanity check of the attribute values
    253       if (pluginName != "" && pluginAssemblies.Count > 0) {
    254         // create a temporary PluginInfo that contains the attribute values
    255         PluginInfo info = new PluginInfo();
     215      if (!string.IsNullOrEmpty(pluginName) &&
     216          pluginFiles.Count > 0 &&
     217          pluginAssemblies.Count > 0) {
     218        // create a temporary PluginDescription that contains the attribute values
     219        PluginDescription info = new PluginDescription();
    256220        info.Name = pluginName;
    257         info.Version = t.Assembly.GetName().Version;
    258         info.Assemblies = pluginAssemblies;
    259         info.Files.AddRange(pluginFiles);
     221        info.Version = pluginType.Assembly.GetName().Version;
     222        info.AddAssemblies(pluginAssemblies);
     223        info.AddFiles(pluginFiles);
     224        info.PluginState = PluginState.Undefined;
     225
    260226        this.pluginDependencies[info] = pluginDependencies;
    261         preloadedPluginInfos.Add(info);
     227        return info;
    262228      } else {
    263         throw new InvalidPluginException();
    264       }
    265     }
    266 
    267     private void CheckPluginDependencies() {
    268       foreach (PluginInfo pluginInfo in preloadedPluginInfos) {
    269         // don't need to check plugins that are already disabled
    270         if (disabledPlugins.Contains(pluginInfo)) {
    271           continue;
    272         }
    273         visitedDependencies.Clear();
    274         if (!CheckPluginDependencies(pluginInfo.Name)) {
    275           PluginInfo matchingInfo = preloadedPluginInfos.Find(delegate(PluginInfo info) { return info.Name == pluginInfo.Name; });
    276           if (matchingInfo == null) throw new InvalidProgramException(); // shouldn't happen
    277           foreach (string dependency in pluginDependencies[matchingInfo]) {
    278             PluginInfo dependencyInfo = new PluginInfo();
    279             dependencyInfo.Name = dependency;
    280             pluginInfo.Dependencies.Add(dependencyInfo);
    281           }
    282 
    283           pluginInfo.Message = "Disabled: missing plugin dependency.";
    284           disabledPlugins.Add(pluginInfo);
    285         }
    286       }
    287     }
    288 
    289     private List<string> visitedDependencies = new List<string>();
    290     private bool CheckPluginDependencies(string pluginName) {
    291       if (!preloadedPluginInfos.Exists(delegate(PluginInfo info) { return pluginName == info.Name; }) ||
    292         disabledPlugins.Exists(delegate(PluginInfo info) { return pluginName == info.Name; }) ||
    293         visitedDependencies.Contains(pluginName)) {
    294         // when the plugin is not available return false;
    295         return false;
    296       } else {
    297         // otherwise check if all dependencies of the plugin are OK
    298         // if yes then this plugin is also ok and we store it in the list of loadable plugins
    299 
    300         PluginInfo matchingInfo = preloadedPluginInfos.Find(delegate(PluginInfo info) { return info.Name == pluginName; });
    301         if (matchingInfo == null) throw new InvalidProgramException(); // shouldn't happen
    302         foreach (string dependency in pluginDependencies[matchingInfo]) {
    303           visitedDependencies.Add(pluginName);
    304           if (CheckPluginDependencies(dependency) == false) {
    305             // if only one dependency is not available that means that the current plugin also is unloadable
    306             return false;
    307           }
    308           visitedDependencies.Remove(pluginName);
    309         }
    310         // all dependencies OK
    311         return true;
    312       }
    313     }
    314 
    315 
    316     private Dictionary<string, IPlugin> pluginsByName = new Dictionary<string, IPlugin>();
    317     private void LoadPlugins() {
     229        throw new InvalidPluginException("Invalid metadata in plugin " + pluginType.ToString());
     230      }
     231    }
     232
     233    private bool IsAttributeDataForType(CustomAttributeData attributeData, Type attributeType) {
     234      return attributeData.Constructor.DeclaringType.AssemblyQualifiedName == attributeType.AssemblyQualifiedName;
     235    }
     236
     237    // builds a dependency tree of all plugin descriptions
     238    // searches matching plugin descriptions based on the list of dependency names for each plugin
     239    // and sets the dependencies in the plugin descriptions
     240    private void BuildDependencyTree(IEnumerable<PluginDescription> pluginDescriptions) {
     241      foreach (var desc in pluginDescriptions) {
     242        foreach (string pluginName in pluginDependencies[desc]) {
     243          var matchingDescriptions = pluginDescriptions.Where(x => x.Name == pluginName);
     244          if (matchingDescriptions.Count() > 0) {
     245            desc.AddDependency(matchingDescriptions.First());
     246          } else {
     247            // no plugin description that matches the dependency name is available => plugin is disabled
     248            desc.PluginState = PluginState.Disabled;
     249            break; // stop processing more dependencies
     250          }
     251        }
     252      }
     253    }
     254
     255    private void CheckPluginDependencies(IEnumerable<PluginDescription> pluginDescriptions) {
     256      foreach (PluginDescription pluginDescription in pluginDescriptions.Where(x => x.PluginState != PluginState.Disabled)) {
     257        if (IsAnyDependencyDisabled(pluginDescription)) {
     258          // PluginDescription.Message = "Disabled: missing plugin dependency.";
     259          pluginDescription.PluginState = PluginState.Disabled;
     260        }
     261      }
     262    }
     263
     264
     265    private bool IsAnyDependencyDisabled(PluginDescription descr) {
     266      if (descr.PluginState == PluginState.Disabled) return true;
     267      foreach (PluginDescription dependency in descr.Dependencies) {
     268        if (IsAnyDependencyDisabled(dependency)) return true;
     269      }
     270      return false;
     271    }
     272
     273    private void LoadPlugins(IEnumerable<PluginDescription> pluginDescriptions) {
    318274      // load all loadable plugins (all dependencies available) into the execution context
    319       foreach (PluginInfo pluginInfo in preloadedPluginInfos) {
    320         if (!disabledPlugins.Contains(pluginInfo)) {
    321           foreach (string assembly in pluginInfo.Assemblies) {
    322             Assembly.LoadFrom(assembly);
    323           }
    324         }
    325       }
    326 
    327       Queue<IPlugin> pluginsToLoad = new Queue<IPlugin>();
    328       DiscoveryService service = new DiscoveryService();
    329       // now search and instantiate an IPlugin type in each loaded assembly
    330       // and prepare the queue to load all plugins
    331       foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) {
    332         // don't search for plugins in the PluginInfrastructure
    333         if (assembly == this.GetType().Assembly)
    334           continue;
    335         Type[] availablePluginTypes = service.GetTypes(typeof(IPlugin), assembly);
    336         foreach (Type pluginType in availablePluginTypes) {
     275      foreach (PluginDescription desc in PluginDescriptionIterator.IterateInDependencyOrder(pluginDescriptions.Where(x => x.PluginState != PluginState.Disabled))) {
     276        List<Type> types = new List<Type>();
     277        foreach (string assembly in desc.Assemblies) {
     278          var asm = Assembly.LoadFrom(assembly);
     279          foreach (Type t in asm.GetTypes()) {
     280            if (typeof(IPlugin).IsAssignableFrom(t)) {
     281              types.Add(t);
     282            }
     283          }
     284        }
     285
     286        foreach (Type pluginType in types) {
    337287          if (!pluginType.IsAbstract && !pluginType.IsInterface && !pluginType.HasElementType) {
    338288            IPlugin plugin = (IPlugin)Activator.CreateInstance(pluginType);
    339             pluginsToLoad.Enqueue(plugin);
    340             pluginsByName.Add(plugin.Name, plugin);
    341           }
    342         }
    343       }
    344 
    345       // load all plugins respecting their dependencies
    346       while (pluginsToLoad.Count > 0) {
    347         IPlugin plugin = pluginsToLoad.Dequeue();
    348         PluginInfo pluginInfo = GetPluginInfo(plugin);
    349         bool canLoad = true;
    350         foreach (PluginInfo dependency in pluginInfo.Dependencies) {
    351           if (!allPlugins.ContainsKey(dependency)) {
    352             canLoad = false;
    353             break;
    354           }
    355         }
    356         if (canLoad) {
    357           PluginAction(this, new PluginManagerActionEventArgs(plugin.Name, PluginManagerAction.InitializingPlugin));
    358           plugin.OnLoad();
    359           allPlugins.Add(pluginInfo, plugin);
    360           PluginAction(this, new PluginManagerActionEventArgs(plugin.Name, PluginManagerAction.InitializedPlugin));
    361         } else {
    362           pluginsToLoad.Enqueue(plugin);
    363         }
    364       }
    365     }
    366     private PluginInfo GetPluginInfo(IPlugin plugin) {
    367       if (pluginInfos.ContainsKey(plugin)) {
    368         return pluginInfos[plugin];
    369       }
    370       // store the data of the plugin in a description file which can be used without loading the plugin assemblies
    371       PluginInfo pluginInfo = new PluginInfo();
    372       pluginInfo.Name = plugin.Name;
    373       pluginInfo.Version = plugin.Version;
    374 
    375       object[] customAttributes = plugin.GetType().Assembly.GetCustomAttributes(typeof(AssemblyBuildDateAttribute), false);
    376       if (customAttributes.Length > 0) {
    377         pluginInfo.BuildDate = ((AssemblyBuildDateAttribute)customAttributes[0]).BuildDate;
    378       }
    379 
    380       string baseDir = AppDomain.CurrentDomain.BaseDirectory;
    381 
    382       Array.ForEach<string>(plugin.FileNames, delegate(string file) {
    383         string filename = pluginDir + "/" + file;
    384         // always use \ as the directory separator
    385         pluginInfo.Files.Add(filename.Replace('/', '\\'));
    386       });
    387 
    388       PluginInfo preloadedInfo = preloadedPluginInfos.Find(delegate(PluginInfo info) { return info.Name == plugin.Name; });
    389       foreach (string assembly in preloadedInfo.Assemblies) {
    390         // always use \ as directory separator (this is necessary for discovery of types in
    391         // plugins see DiscoveryService.GetTypes()
    392         pluginInfo.Assemblies.Add(assembly.Replace('/', '\\'));
    393       }
    394       foreach (string dependency in pluginDependencies[preloadedInfo]) {
    395         // accumulate the dependencies of each assembly into the dependencies of the whole plugin
    396         PluginInfo dependencyInfo = GetPluginInfo(pluginsByName[dependency]);
    397         pluginInfo.Dependencies.Add(dependencyInfo);
    398       }
    399       pluginInfos[plugin] = pluginInfo;
    400       return pluginInfo;
    401     }
    402 
    403     private void CheckPluginFiles() {
    404       foreach (PluginInfo plugin in preloadedPluginInfos) {
    405         if (!CheckPluginFiles(plugin)) {
    406           plugin.Message = "Disabled: missing plugin file.";
    407           disabledPlugins.Add(plugin);
    408         }
    409       }
    410     }
    411 
    412     private bool CheckPluginFiles(PluginInfo pluginInfo) {
    413       foreach (string filename in pluginInfo.Files) {
     289            plugin.OnLoad();
     290            PluginAction(this, new PluginManagerActionEventArgs(plugin.Name, PluginManagerAction.PluginLoaded));
     291          }
     292        }
     293      }
     294    }
     295    //private PluginDescription GetPluginDescription(IPlugin plugin) {
     296    //  if (PluginDescriptions.ContainsKey(plugin)) {
     297    //    return PluginDescriptions[plugin];
     298    //  }
     299    //  // store the data of the plugin in a description file which can be used without loading the plugin assemblies
     300    //  PluginDescription PluginDescription = new PluginDescription();
     301    //  PluginDescription.Name = plugin.Name;
     302    //  PluginDescription.Version = plugin.Version;
     303
     304    //  object[] customAttributes = plugin.GetType().Assembly.GetCustomAttributes(typeof(AssemblyBuildDateAttribute), false);
     305    //  if (customAttributes.Length > 0) {
     306    //    PluginDescription.BuildDate = ((AssemblyBuildDateAttribute)customAttributes[0]).BuildDate;
     307    //  }
     308
     309    //  string baseDir = AppDomain.CurrentDomain.BaseDirectory;
     310
     311    //  Array.ForEach<string>(plugin.FileNames, delegate(string file) {
     312    //    string filename = pluginDir + "/" + file;
     313    //    // always use \ as the directory separator
     314    //    PluginDescription.Files.Add(filename.Replace('/', '\\'));
     315    //  });
     316
     317    //  PluginDescription preloadedInfo = preloadedPluginDescriptions.Find(delegate(PluginDescription info) { return info.Name == plugin.Name; });
     318    //  foreach (string assembly in preloadedInfo.Assemblies) {
     319    //    // always use \ as directory separator (this is necessary for discovery of types in
     320    //    // plugins see DiscoveryService.GetTypes()
     321    //    PluginDescription.Assemblies.Add(assembly.Replace('/', '\\'));
     322    //  }
     323    //  foreach (string dependency in pluginDependencies[preloadedInfo]) {
     324    //    // accumulate the dependencies of each assembly into the dependencies of the whole plugin
     325    //    PluginDescription dependencyInfo = GetPluginDescription(pluginsByName[dependency]);
     326    //    PluginDescription.Dependencies.Add(dependencyInfo);
     327    //  }
     328    //  PluginDescriptions[plugin] = PluginDescription;
     329    //  return PluginDescription;
     330    //}
     331
     332    // checks if all declared plugin files are actually available and disables plugins with missing files
     333    private void CheckPluginFiles(IEnumerable<PluginDescription> pluginDescriptions) {
     334      foreach (PluginDescription desc in pluginDescriptions) {
     335        if (!CheckPluginFiles(desc)) {
     336          //plugin.Message = "Disabled: missing plugin file.";
     337          desc.PluginState = PluginState.Disabled;
     338        }
     339      }
     340    }
     341
     342    private bool CheckPluginFiles(PluginDescription PluginDescription) {
     343      foreach (string filename in PluginDescription.Files) {
    414344        if (!File.Exists(filename)) {
    415           if (MissingPluginFile != null) {
    416             MissingPluginFile(pluginInfo.Name, filename);
    417           }
     345          //if (MissingPluginFile != null) {
     346          //  MissingPluginFile(PluginDescription.Name, filename);
     347          //}
    418348          return false;
    419349        }
     
    429359      return null;
    430360    }
    431 
    432     internal void OnDelete(PluginInfo pluginInfo) {
    433       IPlugin plugin = FindPlugin(pluginInfo);
    434       if (plugin != null) plugin.OnDelete();
    435     }
    436 
    437     internal void OnInstall(PluginInfo pluginInfo) {
    438       IPlugin plugin = FindPlugin(pluginInfo);
    439       if (plugin != null) plugin.OnInstall();
    440     }
    441 
    442     internal void OnPreUpdate(PluginInfo pluginInfo) {
    443       IPlugin plugin = FindPlugin(pluginInfo);
    444       if (plugin != null) plugin.OnPreUpdate();
    445     }
    446 
    447     internal void OnPostUpdate(PluginInfo pluginInfo) {
    448       IPlugin plugin = FindPlugin(pluginInfo);
    449       if (plugin != null) plugin.OnPostUpdate();
    450     }
    451361  }
    452362}
Note: See TracChangeset for help on using the changeset viewer.