public ICommandContext CreateContext(ICommandActor actor, string[] args, string prefix, IReadOnlyCollection <ICommandRegistration> commandRegistrations) { if (actor == null) { throw new ArgumentNullException(nameof(actor)); } if (args == null) { throw new ArgumentNullException(nameof(args)); } var rootCommand = GetCommandRegistration(actor, args[0], commandRegistrations.Where(d => d.ParentId == null)); if (rootCommand == null) { var exceptionContext = new CommandContext(null, actor, args.First(), prefix, args.Skip(1).ToList(), m_LifetimeScope.BeginLifetimeScopeEx()); var localizer = m_LifetimeScope.Resolve <IOpenModStringLocalizer>(); exceptionContext.Exception = new CommandNotFoundException(localizer["commands:errors:not_found", new { CommandName = args[0], Args = args }]); //await actor.PrintMessageAsync(Color.Red, exceptionContext.Exception.Message); return(exceptionContext); } var scope = rootCommand.Component.LifetimeScope.BeginLifetimeScopeEx("AutofacWebRequest"); var rootContext = new CommandContext(rootCommand, actor, args.First(), prefix, args.Skip(1).ToList(), scope); return(BuildContextTree(rootContext, commandRegistrations)); }
public async Task <IOpenModPlugin?> TryActivatePluginAsync(Assembly assembly) { try { if (m_IsDisposing) { throw new ObjectDisposedException(nameof(PluginActivator)); } var pluginMetadata = assembly.GetCustomAttribute <PluginMetadataAttribute>(); if (pluginMetadata == null) { m_Logger.LogError( $"Failed to load plugin from assembly {assembly}: couldn't find any plugin metadata"); return(null); } var pluginTypes = assembly.FindTypes <IOpenModPlugin>().ToList(); if (pluginTypes.Count == 0) { m_Logger.LogError( $"Failed to load plugin from assembly {assembly}: couldn't find any IOpenModPlugin implementation"); return(null); } if (pluginTypes.Count > 1) { m_Logger.LogError( $"Failed to load plugin from assembly {assembly}: assembly has multiple IOpenModPlugin instances"); return(null); } var pluginType = pluginTypes.Single(); IOpenModPlugin pluginInstance; try { var lifetimeScope = m_LifetimeScope.BeginLifetimeScopeEx(containerBuilder => { var workingDirectory = PluginHelper.GetWorkingDirectory(m_Runtime, pluginMetadata.Id); var configurationBuilder = new ConfigurationBuilder(); if (Directory.Exists(workingDirectory)) { configurationBuilder .SetBasePath(workingDirectory) .AddYamlFile("config.yaml", optional: true, reloadOnChange: true); } var configuration = configurationBuilder .AddEnvironmentVariables(pluginMetadata.Id.Replace(".", "_") + "_") .Build(); containerBuilder.Register(_ => configuration) .As <IConfiguration>() .As <IConfigurationRoot>() .SingleInstance() .OwnedByLifetimeScope(); containerBuilder.RegisterType(pluginType) .AsSelf() .As <IOpenModComponent>() .As <IOpenModPlugin>() .SingleInstance() .OwnedByLifetimeScope(); containerBuilder.RegisterType <ScopedPermissionChecker>() .As <IPermissionChecker>() .InstancePerLifetimeScope() .OwnedByLifetimeScope(); containerBuilder.Register(_ => m_DataStoreFactory.CreateDataStore(new DataStoreCreationParameters { #pragma warning disable 618 ComponentId = pluginMetadata.Id, #pragma warning restore 618 Prefix = null, Suffix = "data", WorkingDirectory = workingDirectory })) .As <IDataStore>() .SingleInstance() .OwnedByLifetimeScope(); var stringLocalizer = Directory.Exists(workingDirectory) ? m_StringLocalizerFactory.Create("translations", workingDirectory) : NullStringLocalizer.Instance; containerBuilder.Register(_ => stringLocalizer) .As <IStringLocalizer>() .SingleInstance() .OwnedByLifetimeScope(); var services = ServiceRegistrationHelper.FindFromAssembly <PluginServiceImplementationAttribute>(assembly, m_Logger); var servicesRegistrations = services.OrderBy(d => d.Priority, new PriorityComparer(PriortyComparisonMode.LowestFirst)); foreach (var servicesRegistration in servicesRegistrations) { var implementationType = servicesRegistration.ServiceImplementationType; containerBuilder.RegisterType(implementationType) .As(implementationType) .WithLifetime(servicesRegistration.Lifetime) .OwnedByLifetimeScope(); foreach (var service in servicesRegistration.ServiceTypes) { containerBuilder.Register(c => c.Resolve(implementationType)) .As(service) .WithLifetime(servicesRegistration.Lifetime) .OwnedByLifetimeScope(); } } foreach (var type in pluginType.Assembly.FindTypes <IPluginContainerConfigurator>()) { var configurator = (IPluginContainerConfigurator)ActivatorUtilitiesEx.CreateInstance(m_LifetimeScope, type); configurator.ConfigureContainer(new PluginServiceConfigurationContext(m_LifetimeScope, configuration, containerBuilder)); } var configurationEvent = new PluginContainerConfiguringEvent(pluginMetadata, pluginType, configuration, containerBuilder, workingDirectory); AsyncHelper.RunSync(() => m_EventBus.EmitAsync(m_Runtime, this, configurationEvent)); }); pluginInstance = (IOpenModPlugin)lifetimeScope.Resolve(pluginType); var pluginLoggerType = typeof(ILogger <>).MakeGenericType(pluginType); var pluginLogger = (ILogger)pluginInstance.LifetimeScope.Resolve(pluginLoggerType); RegisterConfigChangeCallback(pluginInstance, pluginLogger); var pluginActivateEvent = new PluginActivatingEvent(pluginInstance); await m_EventBus.EmitAsync(m_Runtime, this, pluginActivateEvent); if (pluginActivateEvent.IsCancelled) { await lifetimeScope.DisposeAsync(); return(null); } } catch (Exception ex) { m_Logger.LogError(ex, $"Failed to load plugin from type: {pluginType.FullName} in assembly: {assembly.FullName}"); return(null); } try { await pluginInstance.LoadAsync(); var serviceProvider = pluginInstance.LifetimeScope.Resolve <IServiceProvider>(); var pluginHelpWriter = ActivatorUtilities.CreateInstance <PluginHelpWriter>(serviceProvider); await pluginHelpWriter.WriteHelpFileAsync(); } catch (Exception ex) { m_Logger.LogError(ex, $"Failed to load plugin: {pluginInstance.DisplayName} v{pluginInstance.Version}"); try { await pluginInstance.LifetimeScope.DisposeAsync(); } catch (Exception e) { m_Logger.LogError(e, "Failed to unload plugin: {DisplayName} v{Version}", pluginInstance.DisplayName, pluginInstance.Version); } return(null); } m_ActivatedPlugins.Add(new WeakReference(pluginInstance)); return(pluginInstance); } catch (Exception ex) { m_Logger.LogError(ex, $"Failed to load plugin from assembly: {assembly.FullName}"); return(null); } }