Lazily init `BasicApiProvider`/`ApiContainer`

This commit is contained in:
James Groom 2023-11-23 06:47:36 +00:00 committed by GitHub
parent 525c9c2f9c
commit 5ef398c309
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 35 additions and 19 deletions

View File

@ -35,7 +35,7 @@ namespace BizHawk.Client.Common
/// Feeds the target its required Apis.
/// </summary>
/// <returns>false if update failed</returns>
public static bool UpdateApis(IExternalApiProvider source, object target)
public static bool UpdateApis(Func<IExternalApiProvider> getProvider, object target)
{
Type targetType = target.GetType();
object[] tmp = new object[1];
@ -44,12 +44,14 @@ namespace BizHawk.Client.Common
.Where(static pi => pi.PropertyType == typeof(ApiContainer))
.Select(static pi => pi.SetMethod))
{
mi?.Invoke(target, new object[] { source.Container });
if (mi is null) continue;
tmp[0] ??= getProvider().Container;
mi.Invoke(target, tmp);
}
foreach (var propinfo in targetType.GetPropertiesWithAttrib(typeof(RequiredApiAttribute)))
{
tmp[0] = source.GetApi(propinfo.PropertyType);
tmp[0] = getProvider().GetApi(propinfo.PropertyType);
if (tmp[0] == null)
{
return false;
@ -60,7 +62,7 @@ namespace BizHawk.Client.Common
foreach (var propinfo in targetType.GetPropertiesWithAttrib(typeof(OptionalApiAttribute)))
{
tmp[0] = source.GetApi(propinfo.PropertyType);
tmp[0] = getProvider().GetApi(propinfo.PropertyType);
propinfo.GetSetMethod(true).Invoke(target, tmp);
}
@ -71,11 +73,10 @@ namespace BizHawk.Client.Common
/// Determines whether a target is available, considering its dependencies
/// and the Apis provided by the emulator core.
/// </summary>
public static bool IsAvailable(IExternalApiProvider source, Type targetType)
public static bool IsAvailable(Func<IExternalApiProvider> getProvider, Type targetType)
{
return targetType.GetPropertiesWithAttrib(typeof(RequiredApiAttribute))
.Select(pi => pi.PropertyType)
.All(source.HasApi);
.All(pi => getProvider().HasApi(pi.PropertyType));
}
}

View File

@ -24,7 +24,9 @@ namespace BizHawk.Client.EmuHawk
private readonly DisplayManager _displayManager;
private readonly ExternalToolManager _extToolManager;
private readonly InputManager _inputManager;
private IExternalApiProvider _apiProvider;
private IExternalApiProvider _apiProvider = null;
private IEmulator _emulator;
private readonly IMovieSession _movieSession;
private IGameInfo _game;
@ -34,12 +36,6 @@ namespace BizHawk.Client.EmuHawk
// Also a UsesRam, and similar method
private readonly List<IToolForm> _tools = new List<IToolForm>();
private IExternalApiProvider ApiProvider
{
get => _apiProvider;
set => _apiProvider = value;
}
/// <summary>
/// Initializes a new instance of the <see cref="ToolManager"/> class.
/// </summary>
@ -61,9 +57,20 @@ namespace BizHawk.Client.EmuHawk
_emulator = emulator;
_movieSession = movieSession;
_game = game;
ApiProvider = ApiManager.Restart(_emulator.ServiceProvider, _owner, _displayManager, _inputManager, _movieSession, this, _config, _emulator, _game);
}
private IExternalApiProvider GetOrInitApiProvider()
=> _apiProvider ??= ApiManager.Restart(
_emulator.ServiceProvider,
_owner,
_displayManager,
_inputManager,
_movieSession,
this,
_config,
_emulator,
_game);
/// <summary>
/// Loads the tool dialog T (T must implements <see cref="IToolForm"/>) , if it does not exist it will be created, if it is already open, it will be focused
/// This method should be used only if you can't use the generic one
@ -165,7 +172,11 @@ namespace BizHawk.Client.EmuHawk
var newTool = (IExternalToolForm) CreateInstance(typeof(IExternalToolForm), toolPath, customFormTypeName, skipExtToolWarning: skipExtToolWarning);
if (newTool == null) return null;
if (newTool is Form form) form.Owner = _owner;
if (!(ServiceInjector.UpdateServices(_emulator.ServiceProvider, newTool) && ApiInjector.UpdateApis(ApiProvider, newTool))) return null;
if (!ServiceInjector.UpdateServices(_emulator.ServiceProvider, newTool)
|| !ApiInjector.UpdateApis(GetOrInitApiProvider, newTool))
{
return null;
}
SetBaseProperties(newTool);
// auto settings
if (newTool is IToolFormAutoConfig autoConfigTool)
@ -557,7 +568,7 @@ namespace BizHawk.Client.EmuHawk
_config = config;
_emulator = emulator;
_game = game;
ApiProvider = ApiManager.Restart(_emulator.ServiceProvider, _owner, _displayManager, _inputManager, _movieSession, this, _config, _emulator, _game);
_apiProvider = null;
// If Cheat tool is loaded, restarting will restart the list too anyway
if (!Has<Cheats>())
{
@ -570,7 +581,7 @@ namespace BizHawk.Client.EmuHawk
{
SetBaseProperties(tool);
if (ServiceInjector.UpdateServices(_emulator.ServiceProvider, tool)
&& (tool is not IExternalToolForm || ApiInjector.UpdateApis(ApiProvider, tool)))
&& (tool is not IExternalToolForm || ApiInjector.UpdateApis(GetOrInitApiProvider, tool)))
{
if (tool.IsActive) tool.Restart();
}
@ -758,7 +769,11 @@ namespace BizHawk.Client.EmuHawk
public bool IsAvailable(Type tool)
{
if (!ServiceInjector.IsAvailable(_emulator.ServiceProvider, tool)) return false;
if (typeof(IExternalToolForm).IsAssignableFrom(tool) && !ApiInjector.IsAvailable(ApiProvider, tool)) return false;
if (typeof(IExternalToolForm).IsAssignableFrom(tool)
&& !ApiInjector.IsAvailable(GetOrInitApiProvider, tool))
{
return false;
}
if (!PossibleToolTypeNames.Contains(tool.AssemblyQualifiedName) && !_extToolManager.PossibleExtToolTypeNames.Contains(tool.AssemblyQualifiedName)) return false; // not a tool
ToolAttribute attr = tool.GetCustomAttributes(false).OfType<ToolAttribute>().SingleOrDefault();