Add and use ReflectionCache classes

This commit is contained in:
YoshiRulz 2020-09-06 22:06:45 +10:00
parent 9325e2f002
commit 209fbc6de0
No known key found for this signature in database
GPG Key ID: C4DE31C245353FB7
31 changed files with 95 additions and 79 deletions

View File

@ -0,0 +1,14 @@
using System;
using System.Reflection;
namespace BizHawk.Client.Common
{
public static class ReflectionCache
{
private static readonly Lazy<Type[]> _types = new Lazy<Type[]>(() => Asm.GetTypes());
public static readonly Assembly Asm = typeof(ReflectionCache).Assembly;
public static Type[] Types => _types.Value;
}
}

View File

@ -9,7 +9,7 @@ namespace BizHawk.Client.Common
{
public static class MovieImport
{
private static readonly Dictionary<Type, ImporterForAttribute> Importers = Assembly.GetAssembly(typeof(ImporterForAttribute)).GetTypes()
private static readonly Dictionary<Type, ImporterForAttribute> Importers = Client.Common.ReflectionCache.Types
.Select(t => (t, attr: (ImporterForAttribute) t.GetCustomAttributes(typeof(ImporterForAttribute)).FirstOrDefault()))
.Where(tuple => tuple.attr != null)
.ToDictionary(tuple => tuple.t, tuple => tuple.attr);

View File

@ -145,7 +145,7 @@ namespace BizHawk.Client.EmuHawk
static VideoWriterInventory()
{
foreach (Type t in typeof(VideoWriterInventory).Assembly.GetTypesWithoutLoadErrors())
foreach (var t in EmuHawk.ReflectionCache.Types)
{
if (!t.IsInterface
&& typeof(IVideoWriter).IsAssignableFrom(t)

View File

@ -3,7 +3,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using BizHawk.Client.Common;
using BizHawk.Common;
@ -15,8 +14,7 @@ namespace BizHawk.Client.EmuHawk
{
/// <remarks>keys are impl., values are interface</remarks>
private static readonly IReadOnlyDictionary<Type, Type> _apiTypes
= Assembly.GetAssembly(typeof(IEmuClientApi)).GetTypes()
.Concat(Assembly.GetAssembly(typeof(EmuClientApi)).GetTypesWithoutLoadErrors())
= Client.Common.ReflectionCache.Types.Concat(EmuHawk.ReflectionCache.Types)
.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

View File

@ -1,7 +1,6 @@
using System;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using BizHawk.Client.EmuHawk.Properties;
using BizHawk.Common;
@ -47,9 +46,7 @@ namespace BizHawk.Client.EmuHawk
VersionLabel.Text = $"Version {mainVersion}";
DateLabel.Text = VersionInfo.ReleaseDate;
var cores = Assembly
.Load("BizHawk.Emulation.Cores")
.GetTypes()
var cores = Emulation.Cores.ReflectionCache.Types
.Where(t => typeof(IEmulator).IsAssignableFrom(t))
.Select(t => t.GetCustomAttributes(false).OfType<CoreAttribute>().FirstOrDefault())
.Where(a => a != null)

View File

@ -153,8 +153,7 @@ namespace BizHawk.Client.EmuHawk
}
var knownServices = Assembly.GetAssembly(typeof(IEmulator))
.GetTypes()
var knownServices = Emulation.Common.ReflectionCache.Types
.Where(t => typeof(IEmulatorService).IsAssignableFrom(t))
.Where(t => t != typeof(IEmulatorService))
.Where(t => t != typeof(ITextStatable)) // Hack for now, eventually we can get rid of this interface in favor of a default implementation
@ -202,10 +201,7 @@ namespace BizHawk.Client.EmuHawk
CoreTree.ImageList.Images.Add("Bad", Properties.Resources.ExclamationRed);
CoreTree.ImageList.Images.Add("Unknown", Properties.Resources.RetroQuestion);
var possibleCoreTypes =
Assembly
.Load("BizHawk.Emulation.Cores")
.GetTypes()
var possibleCoreTypes = Emulation.Cores.ReflectionCache.Types
.Where(t => typeof(IEmulator).IsAssignableFrom(t) && !t.IsAbstract)
.Select(t => new
{

View File

@ -66,20 +66,20 @@ namespace BizHawk.Client.EmuHawk
ShaderChainFrugalizers[i] = new RenderTargetFrugalizer(GL);
}
using (var xml = typeof(Program).Assembly.GetManifestResourceStream("BizHawk.Client.EmuHawk.Resources.courier16px.fnt"))
using (var xml = EmuHawk.ReflectionCache.Asm.GetManifestResourceStream("BizHawk.Client.EmuHawk.Resources.courier16px.fnt"))
{
using var tex = typeof(Program).Assembly.GetManifestResourceStream("BizHawk.Client.EmuHawk.Resources.courier16px_0.png");
using var tex = EmuHawk.ReflectionCache.Asm.GetManifestResourceStream("BizHawk.Client.EmuHawk.Resources.courier16px_0.png");
TheOneFont = new StringRenderer(GL, xml, tex);
}
using (var gens =
typeof(Program).Assembly.GetManifestResourceStream("BizHawk.Client.EmuHawk.Resources.gens.ttf"))
EmuHawk.ReflectionCache.Asm.GetManifestResourceStream("BizHawk.Client.EmuHawk.Resources.gens.ttf"))
{
LoadCustomFont(gens);
}
using (var fceux =
typeof(Program).Assembly.GetManifestResourceStream("BizHawk.Client.EmuHawk.Resources.fceux.ttf"))
EmuHawk.ReflectionCache.Asm.GetManifestResourceStream("BizHawk.Client.EmuHawk.Resources.fceux.ttf"))
{
LoadCustomFont(fceux);
}

View File

@ -1955,9 +1955,7 @@ namespace BizHawk.Client.EmuHawk
}
}
private static readonly IList<Type> _specializedTools = Assembly
.GetAssembly(typeof(MainForm))
.GetTypesWithoutLoadErrors()
private static readonly IList<Type> _specializedTools = EmuHawk.ReflectionCache.Types
.Where(t => typeof(IToolForm).IsAssignableFrom(t) && !t.IsAbstract)
.Where(t => t.GetCustomAttribute<SpecializedToolAttribute>() != null)
.ToList();

View File

@ -1,23 +1,20 @@
using System;
using System.Drawing;
using System.Reflection;
using System.Windows.Forms;
namespace BizHawk.Client.EmuHawk.Properties
{
internal static class Resources
{
private static readonly Assembly Asm = Assembly.GetExecutingAssembly();
/// <param name="embedPath">Dir separator is '<c>.</c>'. Path is relative to <c>&lt;NS></c>.</param>
private static Bitmap ReadEmbeddedBitmapAt(string embedPath) => new Bitmap(Asm.GetManifestResourceStream($"BizHawk.Client.EmuHawk.{embedPath}"));
private static Bitmap ReadEmbeddedBitmapAt(string embedPath) => new Bitmap(EmuHawk.ReflectionCache.Asm.GetManifestResourceStream($"BizHawk.Client.EmuHawk.{embedPath}"));
/// <param name="filename">Dir separator is '<c>.</c>'. Filename is relative to <c>&lt;NS>/images</c> and omits <c>.png</c> extension.</param>
/// <remarks>For other file extensions or paths use <see cref="ReadEmbeddedBitmapAt"/>.</remarks>
private static Bitmap ReadEmbeddedBitmap(string filename) => ReadEmbeddedBitmapAt($"images.{filename}.png");
/// <param name="filename">Dir separator is '<c>.</c>'. Filename is relative to <c>&lt;NS>/images</c> and omits <c>.ico</c> extension.</param>
private static Icon ReadEmbeddedIcon(string filename) => new Icon(Asm.GetManifestResourceStream($"BizHawk.Client.EmuHawk.images.{filename}.ico"));
private static Icon ReadEmbeddedIcon(string filename) => new Icon(EmuHawk.ReflectionCache.Asm.GetManifestResourceStream($"BizHawk.Client.EmuHawk.images.{filename}.ico"));
internal static readonly Lazy<Bitmap> A78Joystick = new Lazy<Bitmap>(() => ReadEmbeddedBitmap("ControllerImages.A78Joystick"));
internal static readonly Lazy<Bitmap> AppleIIKeyboard = new Lazy<Bitmap>(() => ReadEmbeddedBitmap("ControllerImages.AppleIIKeyboard"));
@ -56,7 +53,7 @@ namespace BizHawk.Client.EmuHawk.Properties
internal static readonly Bitmap BackMore = ReadEmbeddedBitmap("BackMore");
internal static readonly Icon BasicBot = ReadEmbeddedIcon("basicbot");
internal static readonly Bitmap Blank = ReadEmbeddedBitmap("Blank");
internal static readonly Cursor BlankCursor = new Cursor(Asm.GetManifestResourceStream("BizHawk.Client.EmuHawk.images.BlankCursor.cur"));
internal static readonly Cursor BlankCursor = new Cursor(EmuHawk.ReflectionCache.Asm.GetManifestResourceStream("BizHawk.Client.EmuHawk.images.BlankCursor.cur"));
internal static readonly Bitmap BlueDown = ReadEmbeddedBitmap("BlueDown");
internal static readonly Bitmap BlueUp = ReadEmbeddedBitmap("BlueUp");
internal static readonly Bitmap Both = ReadEmbeddedBitmap("Both");

View File

@ -0,0 +1,17 @@
using System;
using System.Linq;
using System.Reflection;
using BizHawk.Common;
namespace BizHawk.Client.EmuHawk
{
public static class ReflectionCache
{
private static readonly Lazy<Type[]> _types = new Lazy<Type[]>(() => Asm.GetTypesWithoutLoadErrors().ToArray());
public static readonly Assembly Asm = typeof(ReflectionCache).Assembly;
public static Type[] Types => _types.Value;
}
}

View File

@ -2,7 +2,6 @@
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using NLua;
@ -45,8 +44,7 @@ namespace BizHawk.Client.EmuHawk
Docs.Clear();
// Register lua libraries
foreach (var lib in Assembly.Load("BizHawk.Client.Common").GetTypes()
.Concat(Assembly.GetAssembly(typeof(Win32LuaLibraries)).GetTypesWithoutLoadErrors())
foreach (var lib in Client.Common.ReflectionCache.Types.Concat(EmuHawk.ReflectionCache.Types)
.Where(t => typeof(LuaLibraryBase).IsAssignableFrom(t) && t.IsSealed && ServiceInjector.IsAvailable(serviceProvider, t)))
{
bool addLibrary = true;

View File

@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using BizHawk.Client.Common;
@ -45,7 +44,7 @@ namespace BizHawk.Client.EmuHawk
{
ToolBoxStrip.Items.Clear();
var tools = Assembly.GetAssembly(GetType()).GetTypesWithoutLoadErrors()
var tools = EmuHawk.ReflectionCache.Types
.Where(t => typeof(IToolForm).IsAssignableFrom(t))
.Where(t => typeof(Form).IsAssignableFrom(t))
.Where(t => !typeof(ToolBox).IsAssignableFrom(t))

View File

@ -464,9 +464,7 @@ namespace BizHawk.Client.EmuHawk
return Load<T>(false);
}
public IEnumerable<Type> AvailableTools => Assembly
.GetAssembly(typeof(ToolManager))
.GetTypesWithoutLoadErrors()
public IEnumerable<Type> AvailableTools => EmuHawk.ReflectionCache.Types
.Where(t => typeof(IToolForm).IsAssignableFrom(t))
.Where(t => !t.IsInterface)
.Where(IsAvailable);
@ -701,8 +699,7 @@ namespace BizHawk.Client.EmuHawk
}
private static readonly Lazy<List<string>> LazyAsmTypes = new Lazy<List<string>>(() =>
Assembly.GetAssembly(typeof(ToolManager)) // Confining the search to only EmuHawk, for now at least, we may want to broaden for external tools one day
.GetTypesWithoutLoadErrors()
EmuHawk.ReflectionCache.Types // Confining the search to only EmuHawk, for now at least, we may want to broaden for external tools one day
.Select(t => t.AssemblyQualifiedName)
.ToList());

View File

@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using BizHawk.Common;
@ -73,9 +72,7 @@ namespace BizHawk.Client.EmuHawk
{
ControllerPanel.Controls.Clear();
var schemaType = Assembly
.GetExecutingAssembly()
.GetTypesWithoutLoadErrors()
var schemaType = EmuHawk.ReflectionCache.Types
.Where(t => typeof(IVirtualPadSchema)
.IsAssignableFrom(t) && t.GetCustomAttributes(false)
.OfType<SchemaAttribute>()

View File

@ -0,0 +1,14 @@
using System;
using System.Reflection;
namespace BizHawk.Emulation.Common
{
public static class ReflectionCache
{
private static readonly Lazy<Type[]> _types = new Lazy<Type[]>(() => Asm.GetTypes());
public static readonly Assembly Asm = typeof(ReflectionCache).Assembly;
public static Type[] Types => _types.Value;
}
}

View File

@ -85,8 +85,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
{
if (_controllerTypes == null)
{
_controllerTypes = typeof(Atari2600ControllerDeck).Assembly
.GetTypes()
_controllerTypes = Emulation.Cores.ReflectionCache.Types
.Where(t => typeof(IPort).IsAssignableFrom(t))
.Where(t => !t.IsAbstract && !t.IsInterface)
.ToDictionary(tkey => tkey.DisplayName());

View File

@ -121,8 +121,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
{
if (_controllerTypes == null)
{
_controllerTypes = typeof(A7800HawkControllerDeck).Assembly
.GetTypes()
_controllerTypes = Emulation.Cores.ReflectionCache.Types
.Where(t => typeof(IPort).IsAssignableFrom(t))
.Where(t => !t.IsAbstract && !t.IsInterface)
.ToDictionary(tkey => tkey.DisplayName());

View File

@ -87,8 +87,7 @@ namespace BizHawk.Emulation.Cores.ColecoVision
{
if (_controllerTypes == null)
{
_controllerTypes = typeof(ColecoVisionControllerDeck).Assembly
.GetTypes()
_controllerTypes = Emulation.Cores.ReflectionCache.Types
.Where(t => typeof(IPort).IsAssignableFrom(t))
.Where(t => !t.IsAbstract && !t.IsInterface)
.ToDictionary(tkey => tkey.DisplayName());

View File

@ -76,8 +76,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Vectrex
{
if (_controllerTypes == null)
{
_controllerTypes = typeof(VectrexHawkControllerDeck).Assembly
.GetTypes()
_controllerTypes = Emulation.Cores.ReflectionCache.Types
.Where(t => typeof(IPort).IsAssignableFrom(t))
.Where(t => !t.IsAbstract && !t.IsInterface)
.ToDictionary(tkey => tkey.DisplayName());

View File

@ -76,8 +76,7 @@ namespace BizHawk.Emulation.Cores.Intellivision
{
if (_controllerTypes == null)
{
_controllerTypes = typeof(IntellivisionControllerDeck).Assembly
.GetTypes()
_controllerTypes = Emulation.Cores.ReflectionCache.Types
.Where(t => typeof(IPort).IsAssignableFrom(t))
.Where(t => !t.IsAbstract && !t.IsInterface)
.ToDictionary(tkey => tkey.DisplayName());

View File

@ -102,8 +102,7 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk
{
if (_controllerTypes == null)
{
_controllerTypes = typeof(O2HawkControllerDeck).Assembly
.GetTypes()
_controllerTypes = Emulation.Cores.ReflectionCache.Types
.Where(t => typeof(IPort).IsAssignableFrom(t))
.Where(t => !t.IsAbstract && !t.IsInterface)
.ToDictionary(tkey => tkey.DisplayName());

View File

@ -63,8 +63,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
{
if (_controllerTypes == null)
{
_controllerTypes = typeof(GBHawkControllerDeck).Assembly
.GetTypes()
_controllerTypes = Emulation.Cores.ReflectionCache.Types
.Where(t => typeof(IPort).IsAssignableFrom(t))
.Where(t => !t.IsAbstract && !t.IsInterface)
.ToDictionary(tkey => tkey.DisplayName());

View File

@ -69,8 +69,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink
{
if (_controllerTypes == null)
{
_controllerTypes = typeof(GBHawkLinkControllerDeck).Assembly
.GetTypes()
_controllerTypes = Emulation.Cores.ReflectionCache.Types
.Where(t => typeof(IPort).IsAssignableFrom(t))
.Where(t => !t.IsAbstract && !t.IsInterface)
.ToDictionary(tkey => tkey.DisplayName());

View File

@ -88,8 +88,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink3x
{
if (_controllerTypes == null)
{
_controllerTypes = typeof(GBHawkLink3xControllerDeck).Assembly
.GetTypes()
_controllerTypes = Emulation.Cores.ReflectionCache.Types
.Where(t => typeof(IPort).IsAssignableFrom(t))
.Where(t => !t.IsAbstract && !t.IsInterface)
.ToDictionary(tkey => tkey.DisplayName());

View File

@ -106,8 +106,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink4x
{
if (_controllerTypes == null)
{
_controllerTypes = typeof(GBHawkLink4xControllerDeck).Assembly
.GetTypes()
_controllerTypes = Emulation.Cores.ReflectionCache.Types
.Where(t => typeof(IPort).IsAssignableFrom(t))
.Where(t => !t.IsAbstract && !t.IsInterface)
.ToDictionary(tkey => tkey.DisplayName());

View File

@ -85,7 +85,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
var normalPriority = new List<Type>();
//scan types in this assembly to find ones that implement boards to add them to the list
foreach (Type type in typeof(NES).Assembly.GetTypes())
foreach (var type in Emulation.Cores.ReflectionCache.Types)
{
var attrs = type.GetCustomAttributes(typeof(NesBoardImplAttribute), true);
if (attrs.Length == 0) continue;

View File

@ -1114,15 +1114,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
static readonly Dictionary<string, Type> FamicomExpansions;
static readonly Dictionary<string, Type> NesPortDevices;
static Dictionary<string, Type> Implementors<T>()
{
var assy = typeof(NESControlSettings).Assembly;
var types = assy.GetTypes().Where(c => typeof(T).IsAssignableFrom(c) && !c.IsAbstract && !c.IsInterface);
var ret = new Dictionary<string, Type>();
foreach (Type t in types)
ret[t.Name] = t;
return ret;
}
static Dictionary<string, Type> Implementors<T>() => Emulation.Cores.ReflectionCache.Types
.Where(c => typeof(T).IsAssignableFrom(c) && !c.IsAbstract && !c.IsInterface)
.ToDictionary(t => t.Name, t => t);
static NESControlSettings()
{

View File

@ -69,8 +69,7 @@ namespace BizHawk.Emulation.Cores.Sega.GGHawkLink
{
if (_controllerTypes == null)
{
_controllerTypes = typeof(GGHawkLinkControllerDeck).Assembly
.GetTypes()
_controllerTypes = Emulation.Cores.ReflectionCache.Types
.Where(t => typeof(IPort).IsAssignableFrom(t))
.Where(t => !t.IsAbstract && !t.IsInterface)
.ToDictionary(tkey => tkey.DisplayName());

View File

@ -168,7 +168,7 @@ namespace BizHawk.Emulation.Cores
}
}
public static readonly CoreInventory Instance = new CoreInventory(new[] { typeof(CoreInventory).Assembly });
public static readonly CoreInventory Instance = new CoreInventory(new[] { Emulation.Cores.ReflectionCache.Asm });
}
public enum CorePriority

View File

@ -1,14 +1,11 @@
using System;
using System.Reflection;
using BizHawk.Common.IOExtensions;
namespace BizHawk.Emulation.Cores.Properties {
internal static class Resources {
private static readonly Assembly Asm = typeof(Resources).Assembly;
/// <param name="embedPath">Dir separator is '<c>.</c>'. Path is relative to <c>&lt;NS></c>.</param>
private static byte[] ReadEmbeddedByteArray(string embedPath) => Asm.GetManifestResourceStream($"BizHawk.Emulation.Cores.Resources.{embedPath}").ReadAllBytes();
private static byte[] ReadEmbeddedByteArray(string embedPath) => Emulation.Cores.ReflectionCache.Asm.GetManifestResourceStream($"BizHawk.Emulation.Cores.Resources.{embedPath}").ReadAllBytes();
internal static readonly Lazy<byte[]> CPC_AMSDOS_0_5_ROM = new Lazy<byte[]>(() => ReadEmbeddedByteArray("CPC_AMSDOS_0.5.ROM.gz"));
internal static readonly Lazy<byte[]> CPC_BASIC_1_0_ROM = new Lazy<byte[]>(() => ReadEmbeddedByteArray("CPC_BASIC_1.0.ROM.gz"));

View File

@ -0,0 +1,14 @@
using System;
using System.Reflection;
namespace BizHawk.Emulation.Cores
{
public static class ReflectionCache
{
private static readonly Lazy<Type[]> _types = new Lazy<Type[]>(() => Asm.GetTypes());
public static readonly Assembly Asm = typeof(ReflectionCache).Assembly;
public static Type[] Types => _types.Value;
}
}