Example #1
0
        /// <summary>
        /// Load all plugins<br/>
        /// Flow<br/>
        /// - Get plugin names from website configuration<br/>
        /// - Load plugin information from it's directory<br/>
        /// - Use roslyn compile service compile the source files to assembly<br/>
        /// - Load compiled assembly<br/>
        /// - Register types in assembly to IoC container<br/>
        /// Attention<br/>
        /// - IPlugin will not initliaze here because we may need initialize database before<br/>
        ///   you should invoke IPlugin manually after calling this method<br/>
        /// 加载所有插件<br/>
        /// 流程<br/>
        /// - 从网站配置获取插件名称列表<br/>
        /// - 从插件目录加载插件信息<br/>
        /// - 使用roslyn编译服务编译插件源代码到程序集<br/>
        /// - 加载编译后的程序集<br/>
        /// - 注册程序集中的类型到IoC容器<br/>
        /// 注意<br/>
        /// - 插件不会在这里初始化, 因为我们可能需要在这之前初始化数据库<br/>
        ///   你需要在调用这个函数后手动调用IPlugin接口<br/>
        /// </summary>
        internal protected virtual void Initialize()
        {
            var configManager = Application.Ioc.Resolve <WebsiteConfigManager>();
            var pathManager   = Application.Ioc.Resolve <LocalPathManager>();

            Plugins.Clear();
            PluginAssemblies.Clear();
            // Get plugin names from website configuration
            var pluginDirectories = pathManager.GetPluginDirectories();

            foreach (var pluginName in configManager.WebsiteConfig.Plugins)
            {
                var dir = pluginDirectories
                          .Select(p => PathUtils.SecureCombine(p, pluginName))
                          .FirstOrDefault(p => Directory.Exists(p));
                if (dir == null)
                {
                    throw new DirectoryNotFoundException($"Plugin directory of {pluginName} not found");
                }
                var info = PluginInfo.FromDirectory(dir);
                if (ShouldLoadPlugin(info))
                {
                    Plugins.Add(info);
                }
            }
            // Load plugins
            var assemblyLoader = Application.Ioc.Resolve <IAssemblyLoader>();

            foreach (var plugin in Plugins)
            {
                // Compile plugin
                plugin.Compile();
                // Load compiled assembly, some plugin may not have an assembly
                var assemblyPath = plugin.AssemblyPath();
                if (File.Exists(assemblyPath))
                {
                    // .NET will cache assembly by path, so if assembly contents changed
                    // after plugin recompile, LoadFile will still use the old assembly,
                    // we should load bytes instead of path to avoid caching.
                    var assembly = assemblyLoader.Load(File.ReadAllBytes(assemblyPath));
                    plugin.Assembly = assembly;
                    PluginAssemblies.Add(assembly);
                    PluginAssemblyPathes.Add(assemblyPath);
                }
            }
            // Register types in assembly to IoC container
            // Only public types will be registered
            foreach (var assembly in PluginAssemblies)
            {
                var types = assembly.GetTypes().Where(t => t.IsPublic);
                Application.Ioc.RegisterExports(types);
            }
        }
Example #2
0
 private void AddAssembly(CrmPluginAssembly crmPluginAssembly)
 {
     PluginAssemblies.Add(crmPluginAssembly);
 }
Example #3
0
        /// <summary>
        /// Loads the given Core plugin and any other available plugins, if supported by the environment.
        /// </summary>
        /// <param name="core">The core plugin that controls the environment.</param>
        /// <remarks>
        /// Misc things this function does:
        /// - Delete files scheduled for deletion
        /// - Install pending extensions
        /// </remarks>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="core"/> is null.</exception>
        public virtual async Task LoadCore(CoreSkyEditorPlugin core)
        {
            if (core == null)
            {
                throw new ArgumentNullException(nameof(core));
            }

            // Load providers
            CurrentFileSystem       = core.GetFileSystem();
            CurrentSettingsProvider = core.GetSettingsProvider(this);
            CurrentConsoleProvider  = core.GetConsoleProvider();

            // Delete files and directories scheduled for deletion
            await DeleteScheduledFiles(CurrentSettingsProvider, CurrentFileSystem);

            // Install pending extensions
            ExtensionDirectory = core.GetExtensionDirectory();
            await ExtensionHelper.InstallPendingExtensions(ExtensionDirectory, this);

            // Load the provided core
            CorePluginAssembly = core.GetType().GetTypeInfo().Assembly;
            Plugins.Add(core);
            core.Load(this);

            // Load plugins, if enabled
            if (core.IsPluginLoadingEnabled())
            {
                // Get the paths of all plugins to be loaded
                var supportedPlugins = GetPluginPaths();

                // Load the plugin assemblies
                foreach (var item in supportedPlugins)
                {
                    try
                    {
                        var assemblyActual = core.LoadAssembly(item);
                        if (assemblyActual != null)
                        {
                            PluginAssemblies.Add(assemblyActual);
                            foreach (var plg in assemblyActual.DefinedTypes.Where((x) => ReflectionHelpers.IsOfType(x, typeof(SkyEditorPlugin).GetTypeInfo()) && this.CanCreateInstance(x)))
                            {
                                Plugins.Add(this.CreateInstance(plg) as SkyEditorPlugin);
                            }
                        }
                    }
                    catch (FileLoadException)
                    {
                        // The assembly is a bad assembly.  We can continue loading plugins, but not with this
                        FailedPluginLoads.Add(item);
                    }
                    catch (BadImageFormatException)
                    {
                        // The assembly is a bad assembly.  We can continue loading plugins, but not with this
                        FailedPluginLoads.Add(item);
                    }
                    catch (NotSupportedException)
                    {
                        // The current environment does not support loading assemblies this way.
                        // Abort dynamic assembly loading
                        break;
                    }
                }
            }

            // Load logical plugins
            PluginsLoading?.Invoke(this, new EventArgs());

            var coreType = core.GetType();

            foreach (var item in Plugins.Where(p => p.GetType() != core.GetType()))
            {
                item.Load(this);
            }

            // Load dependant plugins
            while (DependantPluginLoadingQueue.Count > 0)
            {
                var item       = DependantPluginLoadingQueue.Dequeue();
                var pluginType = item.GetType();

                // Determine if it has already been loaded
                if (!Plugins.Where((x) => x.GetType() == pluginType).Any())
                {
                    // Add the plugin
                    Plugins.Add(item);

                    // Add the assembly if it hasn't been added already
                    var pluginAssembly = pluginType.GetTypeInfo().Assembly;
                    if (!PluginAssemblies.Contains(pluginAssembly))
                    {
                        PluginAssemblies.Add(pluginAssembly);
                    }

                    // Load the plugin
                    item.Load(this);
                }
            }

            // Use reflection to fill the type registry
            if (core.IsCorePluginAssemblyDynamicTypeLoadEnabled())
            {
                LoadTypes(CorePluginAssembly);
            }
            if (core.IsExtraPluginAssemblyDynamicTypeLoadEnabled())
            {
                foreach (var item in PluginAssemblies)
                {
                    LoadTypes(item);
                }
            }

            PluginLoadComplete?.Invoke(this, new EventArgs());
        }