Ejemplo n.º 1
0
        public static void MystiqueSetup(this IServiceCollection services)
        {
            services.AddOptions();
            services.AddSingleton <IMvcPluginSetup, MvcPluginSetup>();
            services.AddSingleton <IReferenceContainer, DefaultReferenceContainer>();
            services.AddSingleton <IReferenceLoader, DefaultReferenceLoader>();
            services.AddSingleton <IActionDescriptorChangeProvider>(MystiqueActionDescriptorChangeProvider.Instance);
            services.AddSingleton(MystiqueActionDescriptorChangeProvider.Instance);
            services.AddScoped <PluginPackage>();
            services.AddScoped <IPluginManager, PluginManager>();

            var mvcBuilder = services.AddMvc();

            var pluginFolder  = Path.Combine(Environment.CurrentDirectory, "host_plugins");
            var plugins_cache = Path.Combine(pluginFolder, "plugins_cache.json");

            if (File.Exists(plugins_cache))
            {
                using var scope = services.BuildServiceProvider().CreateScope();
                var refsLoader    = scope.ServiceProvider.GetService <IReferenceLoader>();
                var loggerFactory = scope.ServiceProvider.GetService <ILoggerFactory>();
                var plugins       = JsonConvert.DeserializeObject <PluginModel[]>(File.ReadAllText(plugins_cache, System.Text.Encoding.UTF8));
                foreach (var plugin in plugins)
                {
                    var filePath = Path.Combine(pluginFolder, plugin.Name, $"{plugin.Name}.dll");
                    if (!File.Exists(filePath))
                    {
                        continue;
                    }

                    try
                    {
                        var referenceFolderPath = Path.GetDirectoryName(filePath);
                        using (var fs = new FileStream(filePath, FileMode.Open))
                        {
                            var context  = plugin.PluginContext = new CollectibleAssemblyLoadContext();
                            var assembly = context.LoadFromStream(fs);
                            refsLoader.LoadStreamsIntoContext(context, referenceFolderPath, assembly);

                            var controllerAssemblyPart = new MystiqueAssemblyPart(assembly);
                            mvcBuilder.PartManager.ApplicationParts.Add(controllerAssemblyPart);
                            PluginsLoadContexts.UpsertPluginContext(plugin);
                        }
                        presets.Add(filePath);
                    }
                    catch (Exception ex)
                    {
                        loggerFactory.CreateLogger <CollectibleAssemblyLoadContext>().LogWarning(new EventId(450), $"加载插件失败 '{plugin}'", ex);
                    }
                }
            }

            mvcBuilder.AddRazorRuntimeCompilation(o =>
            {
                foreach (var item in presets)
                {
                    o.AdditionalReferencePaths.Add(item);
                }

                AdditionalReferencePathHolder.AdditionalReferencePaths = o.AdditionalReferencePaths;
            });

            services.Configure <RazorViewEngineOptions>(o =>
            {
                o.AreaViewLocationFormats.Add("/Modules/{2}/Views/{1}/{0}" + RazorViewEngine.ViewExtension);
                o.AreaViewLocationFormats.Add("/Views/Shared/{0}.cshtml");
            });
        }