public static void MystiqueSetup(this IServiceCollection services, IConfiguration configuration) { services.AddOptions(); services.Configure <ConnectionStringSetting>(configuration.GetSection("ConnectionStringSetting")); services.AddSingleton <IMvcModuleSetup, MvcModuleSetup>(); services.AddScoped <IPluginManager, PluginManager>(); services.AddScoped <IUnitOfWork, UnitOfWork>(); services.AddSingleton <IActionDescriptorChangeProvider>(MystiqueActionDescriptorChangeProvider.Instance); services.AddSingleton(MystiqueActionDescriptorChangeProvider.Instance); var mvcBuilder = services.AddMvc().AddRazorRuntimeCompilation(o => { foreach (var item in _presets) { o.AdditionalReferencePaths.Add(item); } AdditionalReferencePathHolder.AdditionalReferencePaths = o.AdditionalReferencePaths; }); var provider = services.BuildServiceProvider(); using (var scope = provider.CreateScope()) { var option = scope.ServiceProvider.GetService <MvcRazorRuntimeCompilationOptions>(); var unitOfWork = scope.ServiceProvider.GetService <IUnitOfWork>(); var allEnabledPlugins = unitOfWork.PluginRepository.GetAllEnabledPlugins(); foreach (var plugin in allEnabledPlugins) { var context = new CollectibleAssemblyLoadContext(); var moduleName = plugin.Name; var filePath = $"{AppDomain.CurrentDomain.BaseDirectory}Modules\\{moduleName}\\{moduleName}.dll"; var referenceFolderPath = $"{AppDomain.CurrentDomain.BaseDirectory}Modules\\{moduleName}"; _presets.Add(filePath); using (var fs = new FileStream(filePath, FileMode.Open)) { var assembly = context.LoadFromStream(fs); DefaultReferenceLoader loader = new DefaultReferenceLoader(referenceFolderPath, $"{moduleName}.dll"); loader.LoadStreamsIntoContext(context); var controllerAssemblyPart = new MystiqueAssemblyPart(assembly); mvcBuilder.PartManager.ApplicationParts.Add(controllerAssemblyPart); PluginsLoadContexts.AddPluginContext(plugin.Name, context); } } } services.Configure <RazorViewEngineOptions>(o => { o.AreaViewLocationFormats.Add("/Modules/{2}/Views/{1}/{0}" + RazorViewEngine.ViewExtension); o.AreaViewLocationFormats.Add("/Views/Shared/{0}.cshtml"); }); }
public static void MystiqueSetup(this IServiceCollection services, IConfiguration configuration) { services.AddOptions(); services.Configure <ConnectionStringSetting>(configuration.GetSection("ConnectionStringSetting")); services.AddSingleton <IMvcModuleSetup, MvcModuleSetup>(); services.AddScoped <IPluginManager, PluginManager>(); services.AddScoped <IUnitOfWork, UnitOfWork>(); services.AddSingleton <INotificationRegister, NotificationRegister>(); services.AddSingleton <IActionDescriptorChangeProvider>(MystiqueActionDescriptorChangeProvider.Instance); services.AddSingleton <IReferenceContainer, DefaultReferenceContainer>(); services.AddSingleton <IReferenceLoader, DefaultReferenceLoader>(); services.AddSingleton(MystiqueActionDescriptorChangeProvider.Instance); IMvcBuilder mvcBuilder = services.AddMvc(); ServiceProvider provider = services.BuildServiceProvider(); using (IServiceScope scope = provider.CreateScope()) { MvcRazorRuntimeCompilationOptions option = scope.ServiceProvider.GetService <MvcRazorRuntimeCompilationOptions>(); IUnitOfWork unitOfWork = scope.ServiceProvider.GetService <IUnitOfWork>(); List <ViewModels.PluginListItemViewModel> allEnabledPlugins = unitOfWork.PluginRepository.GetAllEnabledPlugins(); IReferenceLoader loader = scope.ServiceProvider.GetService <IReferenceLoader>(); foreach (ViewModels.PluginListItemViewModel plugin in allEnabledPlugins) { CollectibleAssemblyLoadContext context = new CollectibleAssemblyLoadContext(plugin.Name); string moduleName = plugin.Name; string filePath = $"{AppDomain.CurrentDomain.BaseDirectory}Modules/{moduleName}/{moduleName}.dll"; string referenceFolderPath = $"{AppDomain.CurrentDomain.BaseDirectory}Modules/{moduleName}"; _presets.Add(filePath); using (FileStream fs = new FileStream(filePath, FileMode.Open)) { System.Reflection.Assembly assembly = context.LoadFromStream(fs); context.SetEntryPoint(assembly); loader.LoadStreamsIntoContext(context, referenceFolderPath, assembly); MystiqueAssemblyPart controllerAssemblyPart = new MystiqueAssemblyPart(assembly); mvcBuilder.PartManager.ApplicationParts.Add(controllerAssemblyPart); PluginsLoadContexts.Add(plugin.Name, context); var providers = assembly.GetExportedTypes().Where(p => p.GetInterfaces().Any(x => x.Name == "INotificationProvider")); if (providers.Any()) { var register = scope.ServiceProvider.GetService <INotificationRegister>(); foreach (var p in providers) { var obj = (INotificationProvider)assembly.CreateInstance(p.FullName); var result = obj.GetNotifications(); foreach (var item in result) { foreach (var i in item.Value) { register.Subscribe(item.Key, i); } } } } } } } mvcBuilder.AddRazorRuntimeCompilation(o => { foreach (string 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"); }); }
public static void MystiqueSetup(this IServiceCollection services, IConfiguration configuration) { _serviceCollection = services; services.AddSingleton <IHttpContextAccessor, HttpContextAccessor>(); services.AddSingleton <IMvcModuleSetup, MvcModuleSetup>(); services.AddScoped <IPluginManager, PluginManager>(); services.AddScoped <ISystemManager, SystemManager>(); services.AddScoped <IUnitOfWork, Repository.MySql.UnitOfWork>(); services.AddSingleton <INotificationRegister, NotificationRegister>(); services.AddSingleton <IActionDescriptorChangeProvider>(MystiqueActionDescriptorChangeProvider.Instance); services.AddSingleton <IReferenceContainer, DefaultReferenceContainer>(); services.AddSingleton <IReferenceLoader, DefaultReferenceLoader>(); services.AddSingleton(MystiqueActionDescriptorChangeProvider.Instance); IMvcBuilder mvcBuilder = services.AddMvc(); ServiceProvider provider = services.BuildServiceProvider(); using (IServiceScope scope = provider.CreateScope()) { IUnitOfWork unitOfWork = scope.ServiceProvider.GetService <IUnitOfWork>(); if (unitOfWork.CheckDatabase()) { List <ViewModels.PluginListItemViewModel> allEnabledPlugins = unitOfWork.PluginRepository.GetAllEnabledPlugins(); IReferenceLoader loader = scope.ServiceProvider.GetService <IReferenceLoader>(); foreach (ViewModels.PluginListItemViewModel plugin in allEnabledPlugins) { CollectibleAssemblyLoadContext context = new CollectibleAssemblyLoadContext(plugin.Name); string moduleName = plugin.Name; string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Modules", moduleName, $"{moduleName}.dll"); string viewFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Modules", moduleName, $"{moduleName}.Views.dll"); string referenceFolderPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Modules", moduleName); _presets.Add(filePath); using (FileStream fs = new FileStream(filePath, FileMode.Open)) { Assembly assembly = context.LoadFromStream(fs); context.SetEntryPoint(assembly); loader.LoadStreamsIntoContext(context, referenceFolderPath, assembly); MystiqueAssemblyPart controllerAssemblyPart = new MystiqueAssemblyPart(assembly); mvcBuilder.PartManager.ApplicationParts.Add(controllerAssemblyPart); PluginsLoadContexts.Add(plugin.Name, context); BuildNotificationProvider(assembly, scope); } using (FileStream fsView = new FileStream(viewFilePath, FileMode.Open)) { Assembly viewAssembly = context.LoadFromStream(fsView); loader.LoadStreamsIntoContext(context, referenceFolderPath, viewAssembly); MystiqueRazorAssemblyPart moduleView = new MystiqueRazorAssemblyPart(viewAssembly, moduleName); mvcBuilder.PartManager.ApplicationParts.Add(moduleView); } context.Enable(); } } } AssemblyLoadContextResoving(); services.Configure <RazorViewEngineOptions>(o => { o.AreaViewLocationFormats.Add("/Modules/{2}/Views/{1}/{0}" + RazorViewEngine.ViewExtension); o.AreaViewLocationFormats.Add("/Views/Shared/{0}.cshtml"); }); services.Replace <IViewCompilerProvider, MystiqueViewCompilerProvider>(); }
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"); }); }