mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-11-11 19:36:28 +00:00
Core/UI - Move from Ninject to DryIoc (#754)
This commit is contained in:
1 parent
166cb888c1
commit
b7e723b7e9
121 files changed
+1175
-980
No files matched your search
@@ -3,11 +3,11 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Artemis.Core.Ninject;
|
||||
using Artemis.Core.DryIoc.Factories;
|
||||
using Artemis.Core.ScriptingProviders;
|
||||
using Artemis.Storage;
|
||||
using DryIoc;
|
||||
using HidSharp;
|
||||
using Ninject;
|
||||
using RGB.NET.Core;
|
||||
using Serilog;
|
||||
using Serilog.Events;
|
||||
@@ -20,7 +20,6 @@ namespace Artemis.Core.Services;
|
||||
/// </summary>
|
||||
internal class CoreService : ICoreService
|
||||
{
|
||||
internal static IKernel? Kernel;
|
||||
private readonly Stopwatch _frameStopWatch;
|
||||
private readonly ILogger _logger;
|
||||
private readonly PluginSetting<LogEventLevel> _loggingLevel;
|
||||
@@ -36,7 +35,7 @@ internal class CoreService : ICoreService
|
||||
private DateTime _lastFrameRateSample;
|
||||
|
||||
// ReSharper disable UnusedParameter.Local
|
||||
public CoreService(IKernel kernel,
|
||||
public CoreService(IContainer container,
|
||||
ILogger logger,
|
||||
StorageMigrationService _1, // injected to ensure migration runs early
|
||||
ISettingsService settingsService,
|
||||
@@ -47,8 +46,7 @@ internal class CoreService : ICoreService
|
||||
IScriptingService scriptingService,
|
||||
IProcessMonitorService _2)
|
||||
{
|
||||
Kernel = kernel;
|
||||
Constants.CorePlugin.Kernel = kernel;
|
||||
Constants.CorePlugin.Container = container;
|
||||
|
||||
_logger = logger;
|
||||
_pluginManagementService = pluginManagementService;
|
||||
@@ -85,19 +83,19 @@ internal class CoreService : ICoreService
|
||||
if (parts.Length == 2 && Enum.TryParse(typeof(LogEventLevel), parts[1], true, out object? logLevelArgument))
|
||||
{
|
||||
_logger.Information("Setting logging level to {loggingLevel} from startup argument", (LogEventLevel) logLevelArgument!);
|
||||
LoggerProvider.LoggingLevelSwitch.MinimumLevel = (LogEventLevel) logLevelArgument;
|
||||
LoggerFactory.LoggingLevelSwitch.MinimumLevel = (LogEventLevel) logLevelArgument;
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Warning("Failed to set log level from startup argument {argument}", argument);
|
||||
_logger.Information("Setting logging level to {loggingLevel}", _loggingLevel.Value);
|
||||
LoggerProvider.LoggingLevelSwitch.MinimumLevel = _loggingLevel.Value;
|
||||
LoggerFactory.LoggingLevelSwitch.MinimumLevel = _loggingLevel.Value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Information("Setting logging level to {loggingLevel}", _loggingLevel.Value);
|
||||
LoggerProvider.LoggingLevelSwitch.MinimumLevel = _loggingLevel.Value;
|
||||
LoggerFactory.LoggingLevelSwitch.MinimumLevel = _loggingLevel.Value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,12 +193,6 @@ internal class CoreService : ICoreService
|
||||
public bool ProfileRenderingDisabled { get; set; }
|
||||
public bool IsElevated { get; set; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
// Dispose services
|
||||
_pluginManagementService.Dispose();
|
||||
}
|
||||
|
||||
public bool IsInitialized { get; set; }
|
||||
|
||||
public void Initialize()
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Artemis.Core.Services;
|
||||
/// <summary>
|
||||
/// A service that initializes the Core and manages the render loop
|
||||
/// </summary>
|
||||
public interface ICoreService : IArtemisService, IDisposable
|
||||
public interface ICoreService : IArtemisService
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets whether the or not the core has been initialized
|
||||
|
||||
@@ -5,8 +5,8 @@ using System.Reflection;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Artemis.Storage.Entities.Profile.Nodes;
|
||||
using DryIoc;
|
||||
using Newtonsoft.Json;
|
||||
using Ninject;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Artemis.Core.Services;
|
||||
@@ -15,17 +15,17 @@ internal class NodeService : INodeService
|
||||
{
|
||||
#region Constants
|
||||
|
||||
private static readonly Type TYPE_NODE = typeof(INode);
|
||||
private static readonly Type TypeNode = typeof(INode);
|
||||
|
||||
#endregion
|
||||
|
||||
private readonly IKernel _kernel;
|
||||
private readonly IContainer _container;
|
||||
|
||||
#region Constructors
|
||||
|
||||
public NodeService(IKernel kernel)
|
||||
public NodeService(IContainer container)
|
||||
{
|
||||
_kernel = kernel;
|
||||
_container = container;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -69,7 +69,7 @@ internal class NodeService : INodeService
|
||||
if (plugin == null) throw new ArgumentNullException(nameof(plugin));
|
||||
if (nodeType == null) throw new ArgumentNullException(nameof(nodeType));
|
||||
|
||||
if (!TYPE_NODE.IsAssignableFrom(nodeType)) throw new ArgumentException("Node has to be a base type of the Node-Type.", nameof(nodeType));
|
||||
if (!TypeNode.IsAssignableFrom(nodeType)) throw new ArgumentException("Node has to be a base type of the Node-Type.", nameof(nodeType));
|
||||
|
||||
NodeAttribute? nodeAttribute = nodeType.GetCustomAttribute<NodeAttribute>();
|
||||
string name = nodeAttribute?.Name ?? nodeType.Name;
|
||||
@@ -106,8 +106,10 @@ internal class NodeService : INodeService
|
||||
|
||||
private INode CreateNode(INodeScript script, NodeEntity? entity, Type nodeType)
|
||||
{
|
||||
INode node = _kernel.Get(nodeType) as INode ?? throw new InvalidOperationException($"Node {nodeType} is not an INode");
|
||||
|
||||
INode node = _container.Resolve(nodeType) as INode ?? throw new InvalidOperationException($"Node {nodeType} is not an INode");
|
||||
if (node is Node concreteNode)
|
||||
concreteNode.Container = _container;
|
||||
|
||||
if (entity != null)
|
||||
{
|
||||
node.X = entity.X;
|
||||
|
||||
@@ -5,19 +5,15 @@ using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Loader;
|
||||
using System.Threading.Tasks;
|
||||
using Artemis.Core.DeviceProviders;
|
||||
using Artemis.Core.Ninject;
|
||||
using Artemis.Core.DryIoc;
|
||||
using Artemis.Storage.Entities.General;
|
||||
using Artemis.Storage.Entities.Plugins;
|
||||
using Artemis.Storage.Entities.Surface;
|
||||
using Artemis.Storage.Repositories.Interfaces;
|
||||
using DryIoc;
|
||||
using McMaster.NETCore.Plugins;
|
||||
using Ninject;
|
||||
using Ninject.Extensions.ChildKernel;
|
||||
using Ninject.Parameters;
|
||||
using Ninject.Planning.Bindings.Resolvers;
|
||||
using RGB.NET.Core;
|
||||
using Serilog;
|
||||
|
||||
@@ -29,7 +25,7 @@ namespace Artemis.Core.Services;
|
||||
internal class PluginManagementService : IPluginManagementService
|
||||
{
|
||||
private readonly IDeviceRepository _deviceRepository;
|
||||
private readonly IKernel _kernel;
|
||||
private readonly IContainer _container;
|
||||
private readonly ILogger _logger;
|
||||
private readonly IPluginRepository _pluginRepository;
|
||||
private readonly List<Plugin> _plugins;
|
||||
@@ -37,9 +33,9 @@ internal class PluginManagementService : IPluginManagementService
|
||||
private bool _disposed;
|
||||
private bool _isElevated;
|
||||
|
||||
public PluginManagementService(IKernel kernel, ILogger logger, IPluginRepository pluginRepository, IDeviceRepository deviceRepository, IQueuedActionRepository queuedActionRepository)
|
||||
public PluginManagementService(IContainer container, ILogger logger, IPluginRepository pluginRepository, IDeviceRepository deviceRepository, IQueuedActionRepository queuedActionRepository)
|
||||
{
|
||||
_kernel = kernel;
|
||||
_container = container;
|
||||
_logger = logger;
|
||||
_pluginRepository = pluginRepository;
|
||||
_deviceRepository = deviceRepository;
|
||||
@@ -198,6 +194,10 @@ internal class PluginManagementService : IPluginManagementService
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
// Disposal happens manually before container disposal but the container doesn't know that so a 2nd call will be made
|
||||
if (_disposed)
|
||||
return;
|
||||
|
||||
_disposed = true;
|
||||
UnloadPlugins();
|
||||
}
|
||||
@@ -340,11 +340,11 @@ internal class PluginManagementService : IPluginManagementService
|
||||
configure.IsUnloadable = true;
|
||||
configure.LoadInMemory = true;
|
||||
configure.PreferSharedTypes = true;
|
||||
|
||||
|
||||
// Resolving failed, try a loaded assembly but ignoring the version
|
||||
configure.DefaultContext.Resolving += (context, assemblyName) => context.Assemblies.FirstOrDefault(a => a.GetName().Name == assemblyName.Name);
|
||||
});
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
plugin.Assembly = plugin.PluginLoader.LoadDefaultAssembly();
|
||||
@@ -406,7 +406,7 @@ internal class PluginManagementService : IPluginManagementService
|
||||
OnPluginLoaded(new PluginEventArgs(plugin));
|
||||
return plugin;
|
||||
}
|
||||
|
||||
|
||||
public void EnablePlugin(Plugin plugin, bool saveState, bool ignorePluginLock)
|
||||
{
|
||||
if (!plugin.Info.IsCompatible)
|
||||
@@ -431,10 +431,17 @@ internal class PluginManagementService : IPluginManagementService
|
||||
if (!plugin.Info.ArePrerequisitesMet())
|
||||
throw new ArtemisPluginPrerequisiteException(plugin.Info, "Cannot enable a plugin whose prerequisites aren't all met");
|
||||
|
||||
// Create the Ninject child kernel and load the module
|
||||
plugin.Kernel = new ChildKernel(_kernel, new PluginModule(plugin));
|
||||
// The kernel used by Core is unforgiving about missing bindings, no need to be so hard on plugin devs
|
||||
plugin.Kernel.Components.Add<IMissingBindingResolver, SelfBindingResolver>();
|
||||
// Create a child container for the plugin, be a bit more forgiving about concrete types
|
||||
plugin.Container = _container.CreateChild(newRules: _container.Rules.WithConcreteTypeDynamicRegistrations());
|
||||
try
|
||||
{
|
||||
new PluginModule(plugin).Load(plugin.Container);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Error(e, "Failed to register plugin services for plugin {plugin}, skipping enabling", plugin);
|
||||
return;
|
||||
}
|
||||
|
||||
OnPluginEnabling(new PluginEventArgs(plugin));
|
||||
|
||||
@@ -446,11 +453,8 @@ internal class PluginManagementService : IPluginManagementService
|
||||
{
|
||||
try
|
||||
{
|
||||
plugin.Kernel.Bind(featureInfo.FeatureType).ToSelf().InSingletonScope();
|
||||
|
||||
// Include Plugin as a parameter for the PluginSettingsProvider
|
||||
IParameter[] parameters = {new Parameter("Plugin", plugin, false)};
|
||||
PluginFeature instance = (PluginFeature) plugin.Kernel.Get(featureInfo.FeatureType, parameters);
|
||||
plugin.Container.Register(featureInfo.FeatureType, reuse: Reuse.Singleton);
|
||||
PluginFeature instance = (PluginFeature) plugin.Container.Resolve(featureInfo.FeatureType);
|
||||
|
||||
// Get the PluginFeature attribute which contains extra info on the feature
|
||||
featureInfo.Instance = instance;
|
||||
@@ -526,8 +530,8 @@ internal class PluginManagementService : IPluginManagementService
|
||||
|
||||
plugin.SetEnabled(false);
|
||||
|
||||
plugin.Kernel?.Dispose();
|
||||
plugin.Kernel = null;
|
||||
plugin.Container?.Dispose();
|
||||
plugin.Container = null;
|
||||
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
|
||||
@@ -9,7 +9,7 @@ using Artemis.Core.Services.Models;
|
||||
using Artemis.Core.SkiaSharp;
|
||||
using Artemis.Storage.Entities.Surface;
|
||||
using Artemis.Storage.Repositories.Interfaces;
|
||||
using Ninject;
|
||||
using DryIoc;
|
||||
using RGB.NET.Core;
|
||||
using Serilog;
|
||||
|
||||
@@ -20,31 +20,36 @@ namespace Artemis.Core.Services;
|
||||
/// </summary>
|
||||
internal class RgbService : IRgbService
|
||||
{
|
||||
private readonly IDeviceRepository _deviceRepository;
|
||||
private readonly List<ArtemisDevice> _devices;
|
||||
private readonly List<ArtemisDevice> _enabledDevices;
|
||||
private readonly IKernel _kernel;
|
||||
private readonly ILogger _logger;
|
||||
private readonly IPluginManagementService _pluginManagementService;
|
||||
private readonly IDeviceRepository _deviceRepository;
|
||||
private readonly LazyEnumerable<IGraphicsContextProvider> _graphicsContextProviders;
|
||||
|
||||
private readonly PluginSetting<string> _preferredGraphicsContext;
|
||||
private readonly PluginSetting<double> _renderScaleSetting;
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly PluginSetting<int> _targetFrameRateSetting;
|
||||
|
||||
private readonly List<ArtemisDevice> _devices;
|
||||
private readonly List<ArtemisDevice> _enabledDevices;
|
||||
private readonly SKTextureBrush _textureBrush = new(null) {CalculationMode = RenderMode.Absolute};
|
||||
private Dictionary<Led, ArtemisLed> _ledMap;
|
||||
private ListLedGroup? _surfaceLedGroup;
|
||||
private SKTexture? _texture;
|
||||
|
||||
public RgbService(ILogger logger, IKernel kernel, ISettingsService settingsService, IPluginManagementService pluginManagementService, IDeviceRepository deviceRepository)
|
||||
public RgbService(ILogger logger,
|
||||
ISettingsService settingsService,
|
||||
IPluginManagementService pluginManagementService,
|
||||
IDeviceRepository deviceRepository,
|
||||
LazyEnumerable<IGraphicsContextProvider> graphicsContextProviders)
|
||||
{
|
||||
_logger = logger;
|
||||
_kernel = kernel;
|
||||
_settingsService = settingsService;
|
||||
_pluginManagementService = pluginManagementService;
|
||||
_deviceRepository = deviceRepository;
|
||||
_graphicsContextProviders = graphicsContextProviders;
|
||||
|
||||
_targetFrameRateSetting = settingsService.GetSetting("Core.TargetFrameRate", 30);
|
||||
_renderScaleSetting = settingsService.GetSetting("Core.RenderScale", 0.25);
|
||||
_preferredGraphicsContext = _settingsService.GetSetting("Core.PreferredGraphicsContext", "Software");
|
||||
_preferredGraphicsContext = settingsService.GetSetting("Core.PreferredGraphicsContext", "Software");
|
||||
|
||||
Surface = new RGBSurface();
|
||||
Utilities.RenderScaleMultiplier = (int) (1 / _renderScaleSetting.Value);
|
||||
@@ -226,7 +231,7 @@ internal class RgbService : IRgbService
|
||||
{
|
||||
_logger.Verbose("[AddDeviceProvider] Updating the LED group");
|
||||
UpdateLedGroup();
|
||||
|
||||
|
||||
_logger.Verbose("[AddDeviceProvider] Resuming rendering after adding {DeviceProvider}", deviceProvider.GetType().Name);
|
||||
if (changedRenderPaused)
|
||||
SetRenderPaused(false);
|
||||
@@ -257,7 +262,7 @@ internal class RgbService : IRgbService
|
||||
{
|
||||
_logger.Verbose("[RemoveDeviceProvider] Updating the LED group");
|
||||
UpdateLedGroup();
|
||||
|
||||
|
||||
_logger.Verbose("[RemoveDeviceProvider] Resuming rendering after adding {DeviceProvider}", deviceProvider.GetType().Name);
|
||||
if (changedRenderPaused)
|
||||
SetRenderPaused(false);
|
||||
@@ -372,7 +377,8 @@ internal class RgbService : IRgbService
|
||||
return;
|
||||
}
|
||||
|
||||
List<IGraphicsContextProvider> providers = _kernel.Get<List<IGraphicsContextProvider>>();
|
||||
|
||||
List<IGraphicsContextProvider> providers = _graphicsContextProviders.ToList();
|
||||
if (!providers.Any())
|
||||
{
|
||||
_logger.Warning("No graphics context provider found, defaulting to software rendering");
|
||||
|
||||
@@ -2,10 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Artemis.Core.ScriptingProviders;
|
||||
using Ninject;
|
||||
using Ninject.Parameters;
|
||||
|
||||
namespace Artemis.Core.Services;
|
||||
|
||||
@@ -51,11 +48,7 @@ internal class ScriptingService : IScriptingService
|
||||
if (provider == null)
|
||||
throw new ArtemisCoreException($"Can't create script instance as there is no matching scripting provider found for the script ({scriptConfiguration.ScriptingProviderId}).");
|
||||
|
||||
script = (GlobalScript) provider.Plugin.Kernel!.Get(
|
||||
provider.GlobalScriptType,
|
||||
CreateScriptConstructorArgument(provider.GlobalScriptType, scriptConfiguration)
|
||||
);
|
||||
|
||||
script = (GlobalScript) provider.Plugin.Resolve(provider.GlobalScriptType, scriptConfiguration);
|
||||
script.ScriptingProvider = provider;
|
||||
script.ScriptingService = this;
|
||||
scriptConfiguration.Script = script;
|
||||
@@ -82,12 +75,7 @@ internal class ScriptingService : IScriptingService
|
||||
if (provider == null)
|
||||
throw new ArtemisCoreException($"Can't create script instance as there is no matching scripting provider found for the script ({scriptConfiguration.ScriptingProviderId}).");
|
||||
|
||||
script = (ProfileScript) provider.Plugin.Kernel!.Get(
|
||||
provider.ProfileScriptType,
|
||||
CreateScriptConstructorArgument(provider.ProfileScriptType, profile),
|
||||
CreateScriptConstructorArgument(provider.ProfileScriptType, scriptConfiguration)
|
||||
);
|
||||
|
||||
script = (ProfileScript) provider.Plugin.Resolve(provider.ProfileScriptType, profile, scriptConfiguration);
|
||||
script.ScriptingProvider = provider;
|
||||
scriptConfiguration.Script = script;
|
||||
provider.InternalScripts.Add(script);
|
||||
@@ -113,21 +101,6 @@ internal class ScriptingService : IScriptingService
|
||||
}
|
||||
}
|
||||
|
||||
private ConstructorArgument CreateScriptConstructorArgument(Type scriptType, object value)
|
||||
{
|
||||
// Limit to one constructor, there's no need to have more and it complicates things anyway
|
||||
ConstructorInfo[] constructors = scriptType.GetConstructors();
|
||||
if (constructors.Length != 1)
|
||||
throw new ArtemisCoreException("Scripts must have exactly one constructor");
|
||||
|
||||
// Find the ScriptConfiguration parameter, it is required by the base constructor so its there for sure
|
||||
ParameterInfo? configurationParameter = constructors.First().GetParameters().FirstOrDefault(p => value.GetType().IsAssignableFrom(p.ParameterType));
|
||||
|
||||
if (configurationParameter?.Name == null)
|
||||
throw new ArtemisCoreException($"Couldn't find a valid constructor argument on {scriptType.Name} with type {value.GetType().Name}");
|
||||
return new ConstructorArgument(configurationParameter.Name, value);
|
||||
}
|
||||
|
||||
private void InitializeProfileScripts(Profile profile)
|
||||
{
|
||||
// Initialize the scripts on the profile
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using EmbedIO.WebApi;
|
||||
using Ninject;
|
||||
|
||||
namespace Artemis.Core.Services;
|
||||
|
||||
@@ -8,7 +7,7 @@ internal class WebApiControllerRegistration<T> : WebApiControllerRegistration wh
|
||||
{
|
||||
public WebApiControllerRegistration(PluginFeature feature) : base(feature, typeof(T))
|
||||
{
|
||||
Factory = () => feature.Plugin.Kernel!.Get<T>();
|
||||
Factory = () => feature.Plugin.Resolve<T>();
|
||||
}
|
||||
|
||||
public Func<T> Factory { get; set; }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
using EmbedIO;
|
||||
using Ninject;
|
||||
using DryIoc;
|
||||
|
||||
namespace Artemis.Core.Services;
|
||||
|
||||
@@ -27,7 +27,7 @@ internal class WebModuleRegistration
|
||||
if (Create != null)
|
||||
return Create();
|
||||
if (WebModuleType != null)
|
||||
return (IWebModule) Feature.Plugin.Kernel!.Get(WebModuleType);
|
||||
return (IWebModule) Feature.Plugin.Resolve(WebModuleType);
|
||||
throw new ArtemisCoreException("WebModuleRegistration doesn't have a create function nor a web module type :(");
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user