From 13ab27ca4ecec798558df30b314a691900390dfb Mon Sep 17 00:00:00 2001 From: YoshiRulz Date: Wed, 5 Aug 2020 23:52:42 +1000 Subject: [PATCH] Simplify API impl. instantiation --- .../Api/Classes/MemoryApi.cs | 9 +--- .../Api/Classes/MemorySaveStateApi.cs | 9 +--- src/BizHawk.Client.EmuHawk/Api/ApiManager.cs | 50 ++++++++----------- .../Api/Libraries/CommApi.cs | 2 +- .../Api/Libraries/EmuClientApi.cs | 2 +- .../Api/Libraries/EmulationApi.cs | 9 +--- .../Api/Libraries/GuiApi.cs | 9 +--- .../Api/Libraries/InputApi.cs | 3 +- .../Api/Libraries/JoypadApi.cs | 9 +--- .../Api/Libraries/MovieApi.cs | 9 +--- .../Api/Libraries/SaveStateApi.cs | 2 +- 11 files changed, 39 insertions(+), 74 deletions(-) diff --git a/src/BizHawk.Client.Common/Api/Classes/MemoryApi.cs b/src/BizHawk.Client.Common/Api/Classes/MemoryApi.cs index f0dcb2f1b2..dabdfc5f67 100644 --- a/src/BizHawk.Client.Common/Api/Classes/MemoryApi.cs +++ b/src/BizHawk.Client.Common/Api/Classes/MemoryApi.cs @@ -17,13 +17,6 @@ namespace BizHawk.Client.Common [OptionalService] private IMemoryDomains MemoryDomainCore { get; set; } - public MemoryApi(Action logCallback) - { - LogCallback = logCallback; - } - - public MemoryApi() : this(Console.WriteLine) {} - private readonly Action LogCallback; private bool _isBigEndian; @@ -63,6 +56,8 @@ namespace BizHawk.Client.Common } } + public MemoryApi(Action logCallback) => LogCallback = logCallback; + private MemoryDomain NamedDomainOrCurrent(string name) { if (!string.IsNullOrEmpty(name)) diff --git a/src/BizHawk.Client.Common/Api/Classes/MemorySaveStateApi.cs b/src/BizHawk.Client.Common/Api/Classes/MemorySaveStateApi.cs index 06a2be5d94..69eefd7b20 100644 --- a/src/BizHawk.Client.Common/Api/Classes/MemorySaveStateApi.cs +++ b/src/BizHawk.Client.Common/Api/Classes/MemorySaveStateApi.cs @@ -9,17 +9,12 @@ namespace BizHawk.Client.Common [RequiredService] private IStatable StatableCore { get; set; } - public MemorySaveStateApi(Action logCallback) - { - LogCallback = logCallback; - } - - public MemorySaveStateApi() : this(Console.WriteLine) {} - private readonly Action LogCallback; private readonly Dictionary _memorySavestates = new Dictionary(); + public MemorySaveStateApi(Action logCallback) => LogCallback = logCallback; + public string SaveCoreStateToMemory() { var guid = Guid.NewGuid(); diff --git a/src/BizHawk.Client.EmuHawk/Api/ApiManager.cs b/src/BizHawk.Client.EmuHawk/Api/ApiManager.cs index a55d4ad846..8c562faae3 100644 --- a/src/BizHawk.Client.EmuHawk/Api/ApiManager.cs +++ b/src/BizHawk.Client.EmuHawk/Api/ApiManager.cs @@ -12,11 +12,20 @@ namespace BizHawk.Client.EmuHawk { public static class ApiManager { - private static readonly Type[] CtorParamTypesA = { typeof(Action), typeof(DisplayManager), typeof(InputManager), typeof(IMainFormForApi) }; + /// keys are impl., values are interface + private static readonly IReadOnlyDictionary _apiTypes + = Assembly.GetAssembly(typeof(IEmuClientApi)).GetTypes() + .Concat(Assembly.GetAssembly(typeof(EmuClientApi)).GetTypes()) + .Where(t => /*t.IsClass &&*/t.IsSealed) // small optimisation; api impl. types are all sealed classes + .Select(t => (t, t.GetInterfaces().FirstOrDefault(t1 => typeof(IExternalApi).IsAssignableFrom(t1) && t1 != typeof(IExternalApi)))) // grab interface from impl. type... + .Where(tuple => tuple.Item2 != null) // ...if we couldn't determine what it's implementing, then it's not an api impl. type + .ToDictionary(tuple => tuple.Item1, tuple => tuple.Item2); - private static readonly Type[] CtorParamTypesB = { typeof(Action) }; + private static readonly Type[] _ctorParamTypesA = { typeof(Action) }; - private static readonly Type[] CtorParamTypesEmuClientApi = { typeof(Action), typeof(DisplayManager), typeof(InputManager), typeof(IMainFormForApi), typeof(Config), typeof(IEmulator), typeof(GameInfo) }; + private static readonly Type[] _ctorParamTypesB = { typeof(Action), typeof(IMainFormForApi) }; + + private static readonly Type[] _ctorParamTypesC = { typeof(Action), typeof(IMainFormForApi), typeof(DisplayManager), typeof(InputManager), typeof(Config), typeof(IEmulator), typeof(GameInfo) }; /// TODO do we need to keep references to these because of GC weirdness? --yoshi private static ApiContainer? _container; @@ -28,32 +37,17 @@ namespace BizHawk.Client.EmuHawk IEmulatorServiceProvider serviceProvider, Action logCallback) { - var libDict = new Dictionary(); - foreach (var api in Assembly.GetAssembly(typeof(IEmuClientApi)).GetTypes() - .Concat(Assembly.GetAssembly(typeof(EmuClientApi)).GetTypes()) - .Where(t => /*t.IsClass && */t.IsSealed - && typeof(IExternalApi).IsAssignableFrom(t) - && ServiceInjector.IsAvailable(serviceProvider, t))) - { - //TODO if extra params are ignored, we can use the same array for every ConstructorInfo.Invoke call --yoshi - object instance; - if (typeof(IEmuClientApi).IsAssignableFrom(api)) - { - instance = (api.GetConstructor(CtorParamTypesEmuClientApi) ?? throw new Exception("failed to call EmuClientApi's hack-filled ctor")) - .Invoke(new object[] { logCallback, GlobalWin.DisplayManager, GlobalWin.InputManager, mainForm, GlobalWin.Config, GlobalWin.Emulator, GlobalWin.Game }); - } - else - { - instance = api.GetConstructor(CtorParamTypesA)?.Invoke(new object[] { logCallback, GlobalWin.DisplayManager, GlobalWin.InputManager, mainForm }) - ?? api.GetConstructor(CtorParamTypesB)?.Invoke(new object[] { logCallback }) - ?? Activator.CreateInstance(api); - } - ServiceInjector.UpdateServices(serviceProvider, instance); - libDict.Add( - api.GetInterfaces().First(intf => typeof(IExternalApi).IsAssignableFrom(intf) && intf != typeof(IExternalApi)), - (IExternalApi) instance + var libDict = _apiTypes.Keys.Where(t => ServiceInjector.IsAvailable(serviceProvider, t)) + .ToDictionary( + t => _apiTypes[t], + t => (IExternalApi) ( + t.GetConstructor(_ctorParamTypesC)?.Invoke(new object[] { logCallback, mainForm, GlobalWin.DisplayManager, GlobalWin.InputManager, GlobalWin.Config, GlobalWin.Emulator, GlobalWin.Game }) + ?? t.GetConstructor(_ctorParamTypesB)?.Invoke(new object[] { logCallback, mainForm }) + ?? t.GetConstructor(_ctorParamTypesA)?.Invoke(new object[] { logCallback }) + ?? Activator.CreateInstance(t) + ) ); - } + foreach (var instance in libDict.Values) ServiceInjector.UpdateServices(serviceProvider, instance); return new ApiContainer(libDict); } diff --git a/src/BizHawk.Client.EmuHawk/Api/Libraries/CommApi.cs b/src/BizHawk.Client.EmuHawk/Api/Libraries/CommApi.cs index 023261ce95..22cc6d3caf 100644 --- a/src/BizHawk.Client.EmuHawk/Api/Libraries/CommApi.cs +++ b/src/BizHawk.Client.EmuHawk/Api/Libraries/CommApi.cs @@ -20,7 +20,7 @@ namespace BizHawk.Client.EmuHawk public WebSocketServer? WebSockets => _wsServer; - public CommApi(Action logCallback, DisplayManager displayManager, InputManager inputManager, IMainFormForApi mainForm) + public CommApi(Action logCallback, IMainFormForApi mainForm) { _networkingHelpers = mainForm.NetworkingHelpers; } diff --git a/src/BizHawk.Client.EmuHawk/Api/Libraries/EmuClientApi.cs b/src/BizHawk.Client.EmuHawk/Api/Libraries/EmuClientApi.cs index ab36967395..bb43314f02 100644 --- a/src/BizHawk.Client.EmuHawk/Api/Libraries/EmuClientApi.cs +++ b/src/BizHawk.Client.EmuHawk/Api/Libraries/EmuClientApi.cs @@ -86,7 +86,7 @@ namespace BizHawk.Client.EmuHawk public event StateSavedEventHandler StateSaved; - public EmuClientApi(Action logCallback, DisplayManager displayManager, InputManager inputManager, IMainFormForApi mainForm, Config config, IEmulator emulator, GameInfo game) + public EmuClientApi(Action logCallback, IMainFormForApi mainForm, DisplayManager displayManager, InputManager inputManager, Config config, IEmulator emulator, GameInfo game) { _config = config; _displayManager = displayManager; diff --git a/src/BizHawk.Client.EmuHawk/Api/Libraries/EmulationApi.cs b/src/BizHawk.Client.EmuHawk/Api/Libraries/EmulationApi.cs index d46a373abb..3b63892bc7 100644 --- a/src/BizHawk.Client.EmuHawk/Api/Libraries/EmulationApi.cs +++ b/src/BizHawk.Client.EmuHawk/Api/Libraries/EmulationApi.cs @@ -37,13 +37,6 @@ namespace BizHawk.Client.EmuHawk [OptionalService] private IRegionable RegionableCore { get; set; } - public EmulationApi(Action logCallback) - { - LogCallback = logCallback; - } - - public EmulationApi() : this(Console.WriteLine) {} - private readonly Action LogCallback; /// Using this property to get a reference to GlobalWin.Config is a terrible, horrible, no good, very bad idea. That's why it's not in the interface. @@ -62,6 +55,8 @@ namespace BizHawk.Client.EmuHawk public Action YieldCallback { get; set; } + public EmulationApi(Action logCallback) => LogCallback = logCallback; + public void DisplayVsync(bool enabled) => GlobalWin.Config.VSync = enabled; public void FrameAdvance() => FrameAdvanceCallback(); diff --git a/src/BizHawk.Client.EmuHawk/Api/Libraries/GuiApi.cs b/src/BizHawk.Client.EmuHawk/Api/Libraries/GuiApi.cs index 04d9d8e17a..f99507cc90 100644 --- a/src/BizHawk.Client.EmuHawk/Api/Libraries/GuiApi.cs +++ b/src/BizHawk.Client.EmuHawk/Api/Libraries/GuiApi.cs @@ -17,13 +17,6 @@ namespace BizHawk.Client.EmuHawk [RequiredService] private IEmulator Emulator { get; set; } - public GuiApi(Action logCallback) - { - LogCallback = logCallback; - } - - public GuiApi() : this(Console.WriteLine) {} - private readonly Action LogCallback; private readonly Dictionary _imageCache = new Dictionary(); @@ -52,6 +45,8 @@ namespace BizHawk.Client.EmuHawk public bool HasGUISurface => _GUISurface != null; + public GuiApi(Action logCallback) => LogCallback = logCallback; + private SolidBrush GetBrush(Color color) => _solidBrushes.TryGetValue(color, out var b) ? b : (_solidBrushes[color] = new SolidBrush(color)); private Pen GetPen(Color color) => _pens.TryGetValue(color, out var p) ? p : (_pens[color] = new Pen(color)); diff --git a/src/BizHawk.Client.EmuHawk/Api/Libraries/InputApi.cs b/src/BizHawk.Client.EmuHawk/Api/Libraries/InputApi.cs index 9a48b84bfb..7f8d598da9 100644 --- a/src/BizHawk.Client.EmuHawk/Api/Libraries/InputApi.cs +++ b/src/BizHawk.Client.EmuHawk/Api/Libraries/InputApi.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Windows.Forms; using BizHawk.Client.Common; +using BizHawk.Emulation.Common; namespace BizHawk.Client.EmuHawk { @@ -15,7 +16,7 @@ namespace BizHawk.Client.EmuHawk private readonly IMainFormForApi _mainForm; - public InputApi(Action logCallback, DisplayManager displayManager, InputManager inputManager, IMainFormForApi mainForm) + public InputApi(Action logCallback, IMainFormForApi mainForm, DisplayManager displayManager, InputManager inputManager, Config config, IEmulator emulator, GameInfo game) { _displayManager = displayManager; _inputManager = inputManager; diff --git a/src/BizHawk.Client.EmuHawk/Api/Libraries/JoypadApi.cs b/src/BizHawk.Client.EmuHawk/Api/Libraries/JoypadApi.cs index 2a3d3569a8..61b5af5a03 100644 --- a/src/BizHawk.Client.EmuHawk/Api/Libraries/JoypadApi.cs +++ b/src/BizHawk.Client.EmuHawk/Api/Libraries/JoypadApi.cs @@ -7,15 +7,10 @@ namespace BizHawk.Client.EmuHawk { public sealed class JoypadApi : IJoypadApi { - public JoypadApi(Action logCallback) - { - LogCallback = logCallback; - } - - public JoypadApi() : this(Console.WriteLine) {} - private readonly Action LogCallback; + public JoypadApi(Action logCallback) => LogCallback = logCallback; + public IDictionary Get(int? controller = null) { return GlobalWin.InputManager.AutofireStickyXorAdapter.ToDictionary(controller); diff --git a/src/BizHawk.Client.EmuHawk/Api/Libraries/MovieApi.cs b/src/BizHawk.Client.EmuHawk/Api/Libraries/MovieApi.cs index 610000e59a..a1ce887684 100644 --- a/src/BizHawk.Client.EmuHawk/Api/Libraries/MovieApi.cs +++ b/src/BizHawk.Client.EmuHawk/Api/Libraries/MovieApi.cs @@ -9,15 +9,10 @@ namespace BizHawk.Client.EmuHawk { public sealed class MovieApi : IMovieApi { - public MovieApi(Action logCallback) - { - LogCallback = logCallback; - } - - public MovieApi() : this(Console.WriteLine) {} - private readonly Action LogCallback; + public MovieApi(Action logCallback) => LogCallback = logCallback; + public bool StartsFromSavestate() => GlobalWin.MovieSession.Movie.IsActive() && GlobalWin.MovieSession.Movie.StartsFromSavestate; public bool StartsFromSaveram() => GlobalWin.MovieSession.Movie.IsActive() && GlobalWin.MovieSession.Movie.StartsFromSaveRam; diff --git a/src/BizHawk.Client.EmuHawk/Api/Libraries/SaveStateApi.cs b/src/BizHawk.Client.EmuHawk/Api/Libraries/SaveStateApi.cs index 6e2665f528..8e1c94855a 100644 --- a/src/BizHawk.Client.EmuHawk/Api/Libraries/SaveStateApi.cs +++ b/src/BizHawk.Client.EmuHawk/Api/Libraries/SaveStateApi.cs @@ -12,7 +12,7 @@ namespace BizHawk.Client.EmuHawk private readonly Action LogCallback; - public SaveStateApi(Action logCallback, DisplayManager displayManager, InputManager inputManager, IMainFormForApi mainForm) + public SaveStateApi(Action logCallback, IMainFormForApi mainForm) { LogCallback = logCallback; _mainForm = mainForm;