DI: Only initialize one renderer at once

This commit is contained in:
Liza 2023-02-17 19:12:44 +01:00
parent 8986b368c7
commit 5419f51942
8 changed files with 94 additions and 32 deletions

View File

@ -48,6 +48,7 @@ namespace Pal.Client
private readonly string _sqliteConnectionString;
private readonly CancellationTokenSource _initCts = new();
private ServiceProvider? _serviceProvider;
private Plugin? _plugin;
public string Name => Localization.Palace_Pal;
@ -122,8 +123,8 @@ namespace Pal.Client
services.AddSingleton<StatisticsWindow>();
// these should maybe be scoped
services.AddSingleton<SimpleRenderer>();
services.AddSingleton<SplatoonRenderer>();
services.AddScoped<SimpleRenderer>();
services.AddScoped<SplatoonRenderer>();
services.AddSingleton<RenderAdapter>();
// queue handling
@ -199,7 +200,7 @@ namespace Pal.Client
_serviceProvider.GetRequiredService<ChatService>();
token.ThrowIfCancellationRequested();
_serviceProvider.GetRequiredService<Plugin>();
_plugin = new Plugin(pluginInterface, _serviceProvider);
_logger.LogInformation("Async init complete");
}
@ -226,15 +227,23 @@ namespace Pal.Client
// ensure we're not calling dispose recursively on ourselves
if (_serviceProvider != null)
{
_logger.LogInformation("Disposing DI Context");
ServiceProvider serviceProvider = _serviceProvider;
_serviceProvider = null;
_plugin?.Dispose();
_plugin = null;
serviceProvider.Dispose();
// ensure we're not keeping the file open longer than the plugin is loaded
using (SqliteConnection sqliteConnection = new(_sqliteConnectionString))
SqliteConnection.ClearPool(sqliteConnection);
}
else
{
_logger.LogDebug("DI context is already disposed");
}
}
}
}

View File

@ -8,6 +8,7 @@ using System.Linq;
using Pal.Client.Properties;
using ECommons;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Pal.Client.Configuration;
namespace Pal.Client
@ -19,24 +20,23 @@ namespace Pal.Client
/// <see cref="DependencyInjection.DependencyInjectionContext"/>
internal sealed class Plugin : IDisposable
{
private readonly IServiceProvider _serviceProvider;
private readonly DalamudPluginInterface _pluginInterface;
private readonly IServiceProvider _serviceProvider;
private readonly ILogger<Plugin> _logger;
private readonly IPalacePalConfiguration _configuration;
private readonly RenderAdapter _renderAdapter;
private readonly WindowSystem _windowSystem;
public Plugin(
IServiceProvider serviceProvider,
DalamudPluginInterface pluginInterface,
IPalacePalConfiguration configuration,
RenderAdapter renderAdapter,
WindowSystem windowSystem)
IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
_pluginInterface = pluginInterface;
_configuration = configuration;
_renderAdapter = renderAdapter;
_windowSystem = windowSystem;
_serviceProvider = serviceProvider;
_logger = _serviceProvider.GetRequiredService<ILogger<Plugin>>();
_configuration = serviceProvider.GetRequiredService<IPalacePalConfiguration>();
_renderAdapter = serviceProvider.GetRequiredService<RenderAdapter>();
_windowSystem = serviceProvider.GetRequiredService<WindowSystem>();
LanguageChanged(pluginInterface.UiLanguage);
@ -65,6 +65,8 @@ namespace Pal.Client
private void LanguageChanged(string languageCode)
{
_logger.LogInformation("Language set to '{Language}'", languageCode);
Localization.Culture = new CultureInfo(languageCode);
_windowSystem.Windows.OfType<ILanguageChanged>()
.Each(w => w.LanguageChanged());

View File

@ -4,5 +4,6 @@
{
TrapHoard,
RegularCoffers,
Test,
}
}

View File

@ -1,15 +1,13 @@
using ImGuiNET;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Collections.Generic;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
using Pal.Client.Configuration;
namespace Pal.Client.Rendering
{
internal interface IRenderer
{
ERenderer GetConfigValue();
void SetLayer(ELayer layer, IReadOnlyList<IRenderElement> elements);
void ResetLayer(ELayer layer);

View File

@ -1,25 +1,55 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Numerics;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Pal.Client.Configuration;
namespace Pal.Client.Rendering
{
internal sealed class RenderAdapter : IRenderer
internal sealed class RenderAdapter : IRenderer, IDisposable
{
private readonly SimpleRenderer _simpleRenderer;
private readonly SplatoonRenderer _splatoonRenderer;
private readonly IServiceScopeFactory _serviceScopeFactory;
private readonly ILogger<RenderAdapter> _logger;
private readonly IPalacePalConfiguration _configuration;
public RenderAdapter(SimpleRenderer simpleRenderer, SplatoonRenderer splatoonRenderer, IPalacePalConfiguration configuration)
private IServiceScope? _renderScope;
public RenderAdapter(IServiceScopeFactory serviceScopeFactory, ILogger<RenderAdapter> logger,
IPalacePalConfiguration configuration)
{
_simpleRenderer = simpleRenderer;
_splatoonRenderer = splatoonRenderer;
_serviceScopeFactory = serviceScopeFactory;
_logger = logger;
_configuration = configuration;
Implementation = Recreate(null);
}
public IRenderer Implementation => _configuration.Renderer.SelectedRenderer == ERenderer.Splatoon
? _splatoonRenderer
: _simpleRenderer;
private IRenderer Recreate(ERenderer? currentRenderer)
{
ERenderer targetRenderer = _configuration.Renderer.SelectedRenderer;
if (targetRenderer == currentRenderer)
return Implementation;
_renderScope?.Dispose();
_logger.LogInformation("Selected new renderer: {Renderer}", _configuration.Renderer.SelectedRenderer);
_renderScope = _serviceScopeFactory.CreateScope();
if (targetRenderer == ERenderer.Splatoon)
return _renderScope.ServiceProvider.GetRequiredService<SplatoonRenderer>();
else
return _renderScope.ServiceProvider.GetRequiredService<SimpleRenderer>();
}
public void ConfigUpdated()
{
Implementation = Recreate(Implementation.GetConfigValue());
}
public void Dispose()
=> _renderScope?.Dispose();
public IRenderer Implementation { get; private set; }
public void SetLayer(ELayer layer, IReadOnlyList<IRenderElement> elements)
=> Implementation.SetLayer(layer, elements);
@ -35,5 +65,8 @@ namespace Pal.Client.Rendering
if (Implementation is SimpleRenderer sr)
sr.DrawLayers();
}
public ERenderer GetConfigValue()
=> throw new NotImplementedException();
}
}

View File

@ -146,6 +146,9 @@ namespace Pal.Client.Rendering
ImGui.GetWindowDrawList().PathClear();
}
public ERenderer GetConfigValue()
=> ERenderer.Simple;
public void Dispose()
{
foreach (var l in _layers.Values)

View File

@ -14,6 +14,7 @@ using System.Reflection;
using Dalamud.Game.ClientState;
using Dalamud.Game.Gui;
using Microsoft.Extensions.Logging;
using Pal.Client.Configuration;
using Pal.Client.DependencyInjection;
using Pal.Client.Extensions;
@ -41,7 +42,7 @@ namespace Pal.Client.Rendering
_clientState = clientState;
_chat = chat;
_logger.LogInformation("Initializing splatoon...");
_logger.LogInformation("Initializing splatoon");
ECommonsMain.Init(pluginInterface, dalamudPlugin, ECommons.Module.SplatoonAPI);
}
@ -117,7 +118,7 @@ namespace Pal.Client.Rendering
CreateElement(Marker.EType.Hoard, pos.Value, ImGui.ColorConvertFloat4ToU32(hoardColor)),
};
if (!Splatoon.AddDynamicElements("PalacePal.Test",
if (!Splatoon.AddDynamicElements(ToLayerName(ELayer.Test),
elements.Cast<SplatoonElement>().Select(x => x.Delegate).ToArray(),
new[] { Environment.TickCount64 + 10000 }))
{
@ -158,12 +159,18 @@ namespace Pal.Client.Rendering
}
}
public ERenderer GetConfigValue()
=> ERenderer.Splatoon;
public void Dispose()
{
_logger.LogInformation("Disposing splatoon");
IsDisposed = true;
ResetLayer(ELayer.TrapHoard);
ResetLayer(ELayer.RegularCoffers);
ResetLayer(ELayer.Test);
ECommonsMain.Dispose();
}

View File

@ -1,6 +1,7 @@
using Microsoft.Extensions.Logging;
using Pal.Client.Configuration;
using Pal.Client.DependencyInjection;
using Pal.Client.Rendering;
namespace Pal.Client.Scheduled
{
@ -11,14 +12,20 @@ namespace Pal.Client.Scheduled
private readonly IPalacePalConfiguration _configuration;
private readonly FloorService _floorService;
private readonly TerritoryState _territoryState;
private readonly RenderAdapter _renderAdapter;
public Handler(ILogger<Handler> logger, IPalacePalConfiguration configuration, FloorService floorService,
TerritoryState territoryState)
public Handler(
ILogger<Handler> logger,
IPalacePalConfiguration configuration,
FloorService floorService,
TerritoryState territoryState,
RenderAdapter renderAdapter)
: base(logger)
{
_configuration = configuration;
_floorService = floorService;
_territoryState = territoryState;
_renderAdapter = renderAdapter;
}
protected override void Run(QueuedConfigUpdate queued, ref bool recreateLayout, ref bool saveMarkers)
@ -33,6 +40,8 @@ namespace Pal.Client.Scheduled
recreateLayout = true;
saveMarkers = true;
}
_renderAdapter.ConfigUpdated();
}
}
}