diff --git a/src/BizHawk.Client.Common/Api/BasicApiProvider.cs b/src/BizHawk.Client.Common/Api/BasicApiProvider.cs index 0e9fc41dd1..033a007315 100644 --- a/src/BizHawk.Client.Common/Api/BasicApiProvider.cs +++ b/src/BizHawk.Client.Common/Api/BasicApiProvider.cs @@ -12,7 +12,7 @@ namespace BizHawk.Client.Common public IReadOnlyCollection AvailableApis => _libs.Keys.ToList(); - public BasicApiProvider(IReadOnlyDictionary libs) => _libs = libs; + public BasicApiProvider(IApiContainer apiContainer) => _libs = apiContainer.Libraries; public object? GetApi(Type t) => _libs.TryGetValue(t, out var api) ? api : null; diff --git a/src/BizHawk.Client.EmuHawk/Api/ApiManager.cs b/src/BizHawk.Client.EmuHawk/Api/ApiManager.cs index 4548170eaf..153e1c482e 100644 --- a/src/BizHawk.Client.EmuHawk/Api/ApiManager.cs +++ b/src/BizHawk.Client.EmuHawk/Api/ApiManager.cs @@ -1,39 +1,49 @@ -using System; +#nullable enable + +using System; using System.Collections.Generic; using System.Linq; using System.Reflection; -using BizHawk.Emulation.Common; using BizHawk.Client.Common; +using BizHawk.Emulation.Common; namespace BizHawk.Client.EmuHawk - { public static class ApiManager { - /// TODO do we need to keep this reference around? --yoshi - private static ApiContainer _container; + private static readonly Type[] CtorParamTypes = { typeof(Action) }; - private static IExternalApiProvider Register(IEmulatorServiceProvider serviceProvider) + /// TODO do we need to keep references to these because of GC weirdness? --yoshi + private static ApiContainer? _container; + + private static ApiContainer? _luaContainer; + + private static ApiContainer Register(IEmulatorServiceProvider serviceProvider, Action logCallback) { + var ctorParamTypes = CtorParamTypes; + var libDict = new Dictionary(); foreach (var api in Assembly.GetAssembly(typeof(ApiSubsetContainer)).GetTypes() .Concat(Assembly.GetAssembly(typeof(ApiContainer)).GetTypes()) - .Where(t => /*t.IsClass && */t.IsSealed && typeof(IExternalApi).IsAssignableFrom(t) && ServiceInjector.IsAvailable(serviceProvider, t))) + .Where(t => /*t.IsClass && */t.IsSealed + && typeof(IExternalApi).IsAssignableFrom(t) + && ServiceInjector.IsAvailable(serviceProvider, t))) { - var instance = (IExternalApi)Activator.CreateInstance(api); + var instance = api.GetConstructor(ctorParamTypes)?.Invoke(new object[] { logCallback }) + ?? Activator.CreateInstance(api); ServiceInjector.UpdateServices(serviceProvider, instance); - Libraries.Add(api.GetInterfaces().First(intf => typeof(IExternalApi).IsAssignableFrom(intf) && intf != typeof(IExternalApi)), instance); + libDict.Add( + api.GetInterfaces().First(intf => typeof(IExternalApi).IsAssignableFrom(intf) && intf != typeof(IExternalApi)), + (IExternalApi) instance + ); } - _container = new ApiContainer(Libraries); - return new BasicApiProvider(Libraries); + return new ApiContainer(libDict); } - private static readonly Dictionary Libraries = new Dictionary(); - public static IExternalApiProvider Restart(IEmulatorServiceProvider newServiceProvider) - { - Libraries.Clear(); - return Register(newServiceProvider); - } + => new BasicApiProvider(_container = Register(newServiceProvider, Console.WriteLine)); + + public static ApiContainer RestartLua(IEmulatorServiceProvider newServiceProvider, Action logCallback) + => _luaContainer = Register(newServiceProvider, logCallback); } } diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/Win32LuaLibraries.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/Win32LuaLibraries.cs index 834217990b..f3bf415c92 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/Win32LuaLibraries.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/Win32LuaLibraries.cs @@ -27,23 +27,6 @@ namespace BizHawk.Client.EmuHawk { _mainForm = mainForm; - static ApiContainer InitApiContainer(IEmulatorServiceProvider sp, Action logCallback) - { - var ctorParamTypes = new[] { typeof(Action) }; - var ctorParams = new object[] { logCallback }; - var libDict = new Dictionary(); - foreach (var api in Assembly.GetAssembly(typeof(EmuApi)).GetTypes() - .Concat(Assembly.GetAssembly(typeof(ToolApi)).GetTypes()) - .Where(t => t.IsSealed && typeof(IExternalApi).IsAssignableFrom(t) && ServiceInjector.IsAvailable(sp, t))) - { - var ctorWithParams = api.GetConstructor(ctorParamTypes); - var instance = (IExternalApi) (ctorWithParams == null ? Activator.CreateInstance(api) : ctorWithParams.Invoke(ctorParams)); - ServiceInjector.UpdateServices(sp, instance); - libDict.Add(api, instance); - } - return ApiContainerInstance = new ApiContainer(libDict); - } - LuaWait = new AutoResetEvent(false); Docs.Clear(); @@ -73,7 +56,7 @@ namespace BizHawk.Client.EmuHawk clientLib.MainForm = _mainForm; } - ApiContainerInstance = InitApiContainer(serviceProvider, ConsoleLuaLibrary.LogOutput); + ApiContainerInstance = ApiManager.RestartLua(serviceProvider, ConsoleLuaLibrary.LogOutput); if (instance is DelegatingLuaLibraryEmu dlgInstanceEmu) dlgInstanceEmu.APIs = ApiContainerInstance; // this is necessary as the property has the `new` modifier else if (instance is DelegatingLuaLibrary dlgInstance) dlgInstance.APIs = ApiContainerInstance;