private static LoadPluginResult LoadPluginFromFolder(string pluginFolderPath, ICollection<string> installedPluginSystemNames)
		{
			Guard.ArgumentNotEmpty(() => pluginFolderPath);

			var folder = new DirectoryInfo(pluginFolderPath);
			if (!folder.Exists)
			{
				return null;
			}

			var descriptionFile = new FileInfo(Path.Combine(pluginFolderPath, "Description.txt"));
			if (!descriptionFile.Exists)
			{
				return null;
			}

			// load descriptor file (Description.txt)
			var descriptor = PluginFileParser.ParsePluginDescriptionFile(descriptionFile.FullName);

			// some validation
			if (descriptor.SystemName.IsEmpty())
			{
				throw new Exception("The plugin descriptor '{0}' does not define a plugin system name. Try assigning the plugin a unique name and recompile.".FormatInvariant(descriptionFile.FullName));
			}
			if (descriptor.PluginFileName.IsEmpty())
			{
				throw new Exception("The plugin descriptor '{0}' does not define a plugin assembly file name. Try assigning the plugin a file name and recompile.".FormatInvariant(descriptionFile.FullName));
			}

			var result = new LoadPluginResult
			{
				DescriptionFile = descriptionFile,
				Descriptor = descriptor
			};

			//ensure that version of plugin is valid
			if (!IsAssumedCompatible(descriptor))
			{
				result.IsIncompatible = true;
				return result;
			}

			if (_referencedPlugins.ContainsKey(descriptor.SystemName))
			{
				throw new Exception(string.Format("A plugin with system name '{0}' is already defined", descriptor.SystemName));
			}

			if (installedPluginSystemNames == null)
			{
				installedPluginSystemNames = PluginFileParser.ParseInstalledPluginsFile();
			}

			// set 'Installed' property
			descriptor.Installed = installedPluginSystemNames.Contains(descriptor.SystemName);

			try
			{
				// get list of all DLLs in plugin folders (not in 'bin' or '_Backup'!)
				var pluginBinaries = descriptionFile.Directory.GetFiles("*.dll", SearchOption.AllDirectories)
					// just make sure we're not registering shadow copied plugins
					.Where(x => IsPackagePluginFolder(x.Directory))
					.ToList();

				// other plugin description info
				var mainPluginFile = pluginBinaries.Where(x => x.Name.IsCaseInsensitiveEqual(descriptor.PluginFileName)).FirstOrDefault();
				descriptor.OriginalAssemblyFile = mainPluginFile;

				// shadow copy main plugin file
				descriptor.ReferencedAssembly = Probe(mainPluginFile);

				if (!descriptor.Installed)
				{
					_inactiveAssemblies.Add(descriptor.ReferencedAssembly);
				}

				// load all other referenced assemblies now
				var otherAssemblies = from x in pluginBinaries
									  where !x.Name.IsCaseInsensitiveEqual(mainPluginFile.Name)
									  select x;

				foreach (var assemblyFile in otherAssemblies)
				{
					if (!IsAlreadyLoaded(assemblyFile))
					{
						Probe(assemblyFile);
					}
				}

				// init plugin type (only one plugin per assembly is allowed)
				var exportedTypes = descriptor.ReferencedAssembly.ExportedTypes;
				bool pluginFound = false;
				bool preStarterFound = !descriptor.Installed;
				foreach (var t in exportedTypes)
				{
					if (typeof(IPlugin).IsAssignableFrom(t) && !t.IsInterface && t.IsClass && !t.IsAbstract)
					{
						descriptor.PluginType = t;
						descriptor.IsConfigurable = typeof(IConfigurable).IsAssignableFrom(t);
						pluginFound = true;
					}
					else if (descriptor.Installed && typeof(IPreApplicationStart).IsAssignableFrom(t) && !t.IsInterface && t.IsClass && !t.IsAbstract && t.HasDefaultConstructor())
					{
						try
						{
							var preStarter = Activator.CreateInstance(t) as IPreApplicationStart;
							preStarter.Start();
						}
						catch { }
						preStarterFound = true;
					}
					if (pluginFound && preStarterFound)
					{
						break;
					}
				}

				result.Success = true;
			}
			catch (ReflectionTypeLoadException ex)
			{
				var msg = string.Empty;
				foreach (var e in ex.LoaderExceptions)
				{
					msg += e.Message + Environment.NewLine;
				}

				var fail = new Exception(msg, ex);
				Debug.WriteLine(fail.Message, fail);

				throw fail;
			}

			return result;
		}
Пример #2
0
        private static LoadPluginResult LoadPluginFromFolder(string pluginFolderPath, ICollection <string> installedPluginSystemNames)
        {
            Guard.ArgumentNotEmpty(() => pluginFolderPath);

            var folder = new DirectoryInfo(pluginFolderPath);

            if (!folder.Exists)
            {
                return(null);
            }

            var descriptionFile = new FileInfo(Path.Combine(pluginFolderPath, "Description.txt"));

            if (!descriptionFile.Exists)
            {
                return(null);
            }

            // load descriptor file (Description.txt)
            var descriptor = PluginFileParser.ParsePluginDescriptionFile(descriptionFile.FullName);

            // some validation
            if (descriptor.SystemName.IsEmpty())
            {
                throw new Exception("The plugin descriptor '{0}' does not define a plugin system name. Try assigning the plugin a unique name and recompile.".FormatInvariant(descriptionFile.FullName));
            }
            if (descriptor.PluginFileName.IsEmpty())
            {
                throw new Exception("The plugin descriptor '{0}' does not define a plugin assembly file name. Try assigning the plugin a file name and recompile.".FormatInvariant(descriptionFile.FullName));
            }

            var result = new LoadPluginResult
            {
                DescriptionFile = descriptionFile,
                Descriptor      = descriptor
            };

            //ensure that version of plugin is valid
            if (!IsAssumedCompatible(descriptor))
            {
                result.IsIncompatible = true;
                return(result);
            }

            if (_referencedPlugins.ContainsKey(descriptor.SystemName))
            {
                throw new Exception(string.Format("A plugin with system name '{0}' is already defined", descriptor.SystemName));
            }

            if (installedPluginSystemNames == null)
            {
                installedPluginSystemNames = PluginFileParser.ParseInstalledPluginsFile();
            }

            // set 'Installed' property
            descriptor.Installed = installedPluginSystemNames.Contains(descriptor.SystemName);

            try
            {
                // get list of all DLLs in plugin folders (not in 'bin' or '_Backup'!)
                var pluginBinaries = descriptionFile.Directory.GetFiles("*.dll", SearchOption.AllDirectories)
                                     // just make sure we're not registering shadow copied plugins
                                     .Where(x => IsPackagePluginFolder(x.Directory))
                                     .ToList();

                // other plugin description info
                var mainPluginFile = pluginBinaries.Where(x => x.Name.IsCaseInsensitiveEqual(descriptor.PluginFileName)).FirstOrDefault();
                descriptor.OriginalAssemblyFile = mainPluginFile;

                // shadow copy main plugin file
                descriptor.ReferencedAssembly = Probe(mainPluginFile);

                if (!descriptor.Installed)
                {
                    _inactiveAssemblies.Add(descriptor.ReferencedAssembly);
                }

                // load all other referenced assemblies now
                var otherAssemblies = from x in pluginBinaries
                                      where !x.Name.IsCaseInsensitiveEqual(mainPluginFile.Name)
                                      select x;

                foreach (var assemblyFile in otherAssemblies)
                {
                    if (!IsAlreadyLoaded(assemblyFile))
                    {
                        Probe(assemblyFile);
                    }
                }

                // init plugin type (only one plugin per assembly is allowed)
                var  exportedTypes   = descriptor.ReferencedAssembly.ExportedTypes;
                bool pluginFound     = false;
                bool preStarterFound = !descriptor.Installed;
                foreach (var t in exportedTypes)
                {
                    if (typeof(IPlugin).IsAssignableFrom(t) && !t.IsInterface && t.IsClass && !t.IsAbstract)
                    {
                        descriptor.PluginType     = t;
                        descriptor.IsConfigurable = typeof(IConfigurable).IsAssignableFrom(t);
                        pluginFound = true;
                    }
                    else if (descriptor.Installed && typeof(IPreApplicationStart).IsAssignableFrom(t) && !t.IsInterface && t.IsClass && !t.IsAbstract && t.HasDefaultConstructor())
                    {
                        try
                        {
                            var preStarter = Activator.CreateInstance(t) as IPreApplicationStart;
                            preStarter.Start();
                        }
                        catch { }
                        preStarterFound = true;
                    }
                    if (pluginFound && preStarterFound)
                    {
                        break;
                    }
                }

                result.Success = true;
            }
            catch (ReflectionTypeLoadException ex)
            {
                var msg = string.Empty;
                foreach (var e in ex.LoaderExceptions)
                {
                    msg += e.Message + Environment.NewLine;
                }

                var fail = new Exception(msg, ex);
                Debug.WriteLine(fail.Message, fail);

                throw fail;
            }

            return(result);
        }