/// <summary>
        /// 应用指定的加载配置进行插件加载。
        /// </summary>
        /// <param name="settings">指定的加载配置对象。</param>
        /// <remarks>
        ///		<para>使用不同的<see cref="Zongsoft.Plugins.PluginLoaderSetup"/>设置项多次加载,会导致最后一次加载覆盖上次加载的插件结构,这有可能会影响您的插件应用对构件或服务的获取路径,从而导致不可预知的结果。</para>
        ///		<para>如果要重用上次加载的配置,请调用无参的Load方法。</para>
        ///	</remarks>
        /// <exception cref="System.ArgumentNullException">参数<paramref name="settings"/>为空(null)。</exception>
        public void Load(PluginLoaderSetup settings)
        {
            if (settings == null)
            {
                throw new ArgumentNullException("settings");
            }

            //激发“Loading”事件
            this.OnLoading(new PluginLoadEventArgs(settings));

            //如果指定的目录路径不存在则激发“Failure”事件,并退出
            if (!Directory.Exists(_settings.PluginsDirectory))
            {
                throw new DirectoryNotFoundException(string.Format("The '{0}' plugins directory is not exists.", _settings.PluginsDirectory));
            }

            //清空插件列表
            _plugins.Clear();

            //预加载插件目录下的所有插件文件
            this.PreloadPluginFiles(_settings.PluginsDirectory, null, settings);

            //正式加载所有插件
            this.LoadPlugins(_plugins, settings);

            //保存加载配置对象
            _settings = settings;

            //激发“Loaded”事件
            this.OnLoaded(new PluginLoadEventArgs(settings));
        }
示例#2
0
        private void LoadPlugins(PluginCollection plugins, PluginLoaderSetup settings)
        {
            if (plugins == null || plugins.Count < 1)
            {
                return;
            }

            var stack = new Stack <Plugin>();

            //注意:①. 先加载同级插件
            foreach (var plugin in plugins)
            {
                //确保同级插件栈内的所有插件一定都是未加载的插件
                if (plugin.Status == PluginStatus.Loading)
                {
                    this.TryPushToStack(plugin, stack);
                    this.LoadPlugin(stack, pluginName => plugins[pluginName], settings);
                }
            }

            //注意:②. 再依次加载各个子插件
            foreach (var plugin in plugins)
            {
                if (plugin.Status == PluginStatus.Loaded)
                {
                    this.LoadPlugins(plugin.Children, settings);
                }
            }
        }
        public PluginLoadEventArgs(PluginLoaderSetup settings)
        {
            if (settings == null)
            {
                throw new ArgumentNullException("settings");
            }

            this.Settings = settings;
        }
示例#4
0
        public PluginLoadedEventArgs(PluginLoaderSetup settings, Plugin plugin) : base(settings)
        {
            if (plugin == null)
            {
                throw new ArgumentNullException("plugin");
            }

            this.Plugin = plugin;
        }
示例#5
0
        public PluginLoadingEventArgs(PluginLoaderSetup settings, string pluginFile) : base(settings)
        {
            if (string.IsNullOrEmpty(pluginFile))
            {
                throw new ArgumentNullException("pluginFile");
            }

            this.PluginFile = pluginFile;
        }
示例#6
0
        /// <summary>
        /// 应用指定的设置加载插件树。
        /// </summary>
        /// <param name="settings">指定的插件加载器配置对象。</param>
        /// <exception cref="System.ArgumentNullException">参数<paramref name="settings"/>为空(null)。</exception>
        public void Load(PluginLoaderSetup settings)
        {
            if (settings == null)
            {
                throw new ArgumentNullException("settings");
            }

            //应用指定的设置进行加载
            this.Loader.Load(settings);
        }
        private void PreloadPluginChildrenFiles(string directoryPath, Plugin parent, PluginLoaderSetup settings)
        {
            //获取当前插件目录的下级子目录
            string[] childDirectoriePaths = Directory.GetDirectories(directoryPath);

            //依次加载子目录下的所有插件
            foreach (string childDirectoryPath in childDirectoriePaths)
            {
                this.PreloadPluginFiles(childDirectoryPath, parent, settings);
            }
        }
        internal PluginLoader(PluginResolver resolver, PluginLoaderSetup setup)
        {
            if (resolver == null)
            {
                throw new ArgumentNullException("resolver");
            }

            _resolver = resolver;
            _settings = setup;
            _plugins  = new PluginCollection();
        }
示例#9
0
        private void PreloadPluginFiles(string directoryPath, Plugin parent, PluginLoaderSetup settings)
        {
            //获取指定目录下的插件文件
            var filePaths = Directory.GetFiles(directoryPath, "*.plugin", SearchOption.TopDirectoryOnly);

            //如果当前目录下没有插件文件则查找子目录
            if (filePaths == null || filePaths.Length < 1)
            {
                this.PreloadPluginChildrenFiles(directoryPath, parent, settings);
                return;
            }

            //已经成功加载的主插件列表
            var masters = new List <Plugin>();

            //注意:取消了对返回的文件名数组进行排序(包含文件扩展名的排序是不准的)
            //Array.Sort<string>(filePaths, StringComparer.Ordinal);

            //依次加载所有插件文件
            foreach (string filePath in filePaths)
            {
                //首先加载插件文件的清单信息(根据清单信息中的依赖插件来决定是否需要完整加载)
                Plugin plugin = this.LoadPluginManifest(filePath, parent, settings);

                //如果预加载失败,则跳过以进行下一个插件文件的处理
                if (plugin == null || plugin.Status == PluginStatus.Failed)
                {
                    continue;
                }

                //判断当前预加载的插件是否为主插件
                if (plugin.IsMaster)
                {
                    //将当前已完整加载的插件加入主插件列表中
                    masters.Add(plugin);
                }
            }

            //定义子插件的父插件,默认为当前插件目录的父插件
            Plugin ownerPlugin = parent;

            //如果当前插件目录下有主插件则所有子插件的父为第一个主插件
            if (masters.Count > 0)
            {
                ownerPlugin = masters[0];
            }

            //预加载子插件
            this.PreloadPluginChildrenFiles(directoryPath, ownerPlugin, settings);
        }
示例#10
0
        private void LoadPlugins(PluginCollection plugins, PluginLoaderSetup settings)
        {
            if (plugins == null || plugins.Count < 1)
            {
                return;
            }

            Plugin hidden = null;
            var    stack  = new Stack <Plugin>();

            //注意:①. 先加载同级插件(忽略隐藏式插件)
            foreach (var plugin in plugins)
            {
                //确保同级插件栈内的所有插件一定都是未加载的插件
                if (plugin.Status == PluginStatus.Loading)
                {
                    //如果是隐藏式插件,则先忽略它,放待最后再来加载
                    if (plugin.IsHidden)
                    {
                        hidden = plugin;
                    }
                    else
                    {
                        this.TryPushToStack(plugin, stack);
                        this.LoadPlugin(stack, pluginName => (plugins.TryGet(pluginName, out var found) ? found : null), settings);
                    }
                }
            }

            //注意:②. 再依次加载各个子插件
            foreach (var plugin in plugins)
            {
                if (plugin.Status == PluginStatus.Loaded)
                {
                    this.LoadPlugins(plugin.Children, settings);
                }
            }

            //注意:③. 如果当前层级中含有隐藏式插件,则留待最后再来加载它
            if (hidden != null)
            {
                this.TryPushToStack(hidden, stack);
                this.LoadPlugin(stack, pluginName => (plugins.TryGet(pluginName, out var found) ? found : null), settings);
            }
        }
示例#11
0
        private Plugin LoadPluginManifest(string filePath, Plugin parent, PluginLoaderSetup settings)
        {
            //激发“PluginLoading”事件
            this.OnPluginLoading(new PluginLoadingEventArgs(settings, filePath));

            //解析插件清单
            Plugin plugin = _resolver.ResolvePluginOnlyManifest(filePath, parent);

            if (plugin == null)
            {
                return(null);
            }

            //设置插件状态
            plugin.Status = PluginStatus.Loading;

            if (parent == null)
            {
                if (_plugins.Any(p => string.Equals(p.Name, plugin.Name, StringComparison.OrdinalIgnoreCase)))
                {
                    plugin.Status            = PluginStatus.Failed;
                    plugin.StatusDescription = string.Format("The name is '{0}' of plugin was exists. it's path is: '{1}'", plugin.Name, plugin.FilePath);

                    //抛出插件文件异常(原因为插件名称重复)
                    throw new PluginFileException(plugin.FilePath, $"The name is '{plugin.Name}' of plugin was exists. it's path is: '{plugin.FilePath}'");
                }

                //将预加载的插件对象加入到根插件的集合中
                _plugins.Add(plugin);
            }
            else
            {
                //将预加载的插件对象加入到父插件的子集中,如果返回假则表示加载失败
                if (!parent.Children.Add(plugin, false))
                {
                    plugin.Status            = PluginStatus.Failed;
                    plugin.StatusDescription = string.Format("The name is '{0}' of plugin was exists. it's path is: '{1}'", plugin.Name, plugin.FilePath);

                    //抛出插件文件异常(原因为插件名称重复)
                    throw new PluginFileException(plugin.FilePath, $"The name is '{plugin.Name}' of plugin was exists. it's path is: '{plugin.FilePath}'");
                }
            }

            return(plugin);
        }
示例#12
0
        private void LoadPluginContent(Plugin plugin, PluginLoaderSetup settings)
        {
            if (plugin == null)
            {
                throw new ArgumentNullException("plugin");
            }

            if (plugin.Status != PluginStatus.Loading)
            {
                return;
            }

            try
            {
                //解析插件对象
                _resolver.ResolvePluginWithoutManifest(plugin);

                //设置已加载插件对象所属应用域的私有路径(测试用代码)
                PluginContainer.SetPrivatePath(plugin.FilePath, AppDomain.CurrentDomain);

                //设置插件状态
                plugin.Status = PluginStatus.Loaded;

                //激发“PluginLoaded”事件
                this.OnPluginLoaded(new PluginLoadedEventArgs(settings, plugin));
            }
            catch (Exception ex)
            {
                plugin.Status            = PluginStatus.Failed;
                plugin.StatusDescription = ex.Message;

                if (plugin.Parent == null)
                {
                    _plugins.Remove(plugin.Name);
                }
                else
                {
                    plugin.Parent.Children.Remove(plugin.Name);
                }

                throw new PluginFileException(plugin.FilePath, $"The '{plugin.FilePath}' plugin file resolve failed.", ex);
            }
        }
示例#13
0
        private void LoadPlugin(Stack <Plugin> stack, Func <string, Plugin> dependencyThunk, PluginLoaderSetup settings)
        {
            if (stack == null || stack.Count < 1)
            {
                return;
            }

            var plugin = stack.Peek();

            if (this.IsRequiredLoad(plugin, dependencyThunk))
            {
                this.LoadPluginContent(stack.Pop(), settings);
            }
            else
            {
                foreach (var dependency in plugin.Manifest.Dependencies)
                {
                    if (this.IsRequiredLoad(dependency.Plugin, dependencyThunk))
                    {
                        this.LoadPluginContent(dependency.Plugin, settings);
                    }
                    else
                    {
                        this.TryPushToStack(dependency.Plugin, stack);
                    }
                }
            }

            if (stack.Count > 0)
            {
                this.LoadPlugin(stack, dependencyThunk, settings);
            }
        }