Unify ApiContainer instantiation

fixes c1cd1b9e0
This commit is contained in:
YoshiRulz 2020-05-24 14:19:14 +10:00
parent af2f460356
commit 5b5b6bd483
No known key found for this signature in database
GPG Key ID: C4DE31C245353FB7
3 changed files with 29 additions and 36 deletions

View File

@ -12,7 +12,7 @@ namespace BizHawk.Client.Common
public IReadOnlyCollection<Type> AvailableApis => _libs.Keys.ToList();
public BasicApiProvider(IReadOnlyDictionary<Type, IExternalApi> libs) => _libs = libs;
public BasicApiProvider(IApiContainer apiContainer) => _libs = apiContainer.Libraries;
public object? GetApi(Type t) => _libs.TryGetValue(t, out var api) ? api : null;

View File

@ -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
{
/// <remarks>TODO do we need to keep this reference around? --yoshi</remarks>
private static ApiContainer _container;
private static readonly Type[] CtorParamTypes = { typeof(Action<string>) };
private static IExternalApiProvider Register(IEmulatorServiceProvider serviceProvider)
/// <remarks>TODO do we need to keep references to these because of GC weirdness? --yoshi</remarks>
private static ApiContainer? _container;
private static ApiContainer? _luaContainer;
private static ApiContainer Register(IEmulatorServiceProvider serviceProvider, Action<string> logCallback)
{
var ctorParamTypes = CtorParamTypes;
var libDict = new Dictionary<Type, IExternalApi>();
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<Type, IExternalApi> Libraries = new Dictionary<Type, IExternalApi>();
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<string> logCallback)
=> _luaContainer = Register(newServiceProvider, logCallback);
}
}

View File

@ -27,23 +27,6 @@ namespace BizHawk.Client.EmuHawk
{
_mainForm = mainForm;
static ApiContainer InitApiContainer(IEmulatorServiceProvider sp, Action<string> logCallback)
{
var ctorParamTypes = new[] { typeof(Action<string>) };
var ctorParams = new object[] { logCallback };
var libDict = new Dictionary<Type, IExternalApi>();
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;