From 0a69cb4bf71e6e822e595141ce5f24009e509246 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 16 Apr 2022 19:15:50 -0400 Subject: allow switching between Pintail & original API proxying --- .../Reflection/OriginalInterfaceProxyFactory.cs | 57 ++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 src/SMAPI/Framework/Reflection/OriginalInterfaceProxyFactory.cs (limited to 'src/SMAPI/Framework/Reflection/OriginalInterfaceProxyFactory.cs') diff --git a/src/SMAPI/Framework/Reflection/OriginalInterfaceProxyFactory.cs b/src/SMAPI/Framework/Reflection/OriginalInterfaceProxyFactory.cs new file mode 100644 index 00000000..d6966978 --- /dev/null +++ b/src/SMAPI/Framework/Reflection/OriginalInterfaceProxyFactory.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Reflection.Emit; + +namespace StardewModdingAPI.Framework.Reflection +{ + /// + internal class OriginalInterfaceProxyFactory : IInterfaceProxyFactory + { + /********* + ** Fields + *********/ + /// The CLR module in which to create proxy classes. + private readonly ModuleBuilder ModuleBuilder; + + /// The generated proxy types. + private readonly IDictionary Builders = new Dictionary(); + + + /********* + ** Public methods + *********/ + /// Construct an instance. + public OriginalInterfaceProxyFactory() + { + AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName($"StardewModdingAPI.Proxies, Version={this.GetType().Assembly.GetName().Version}, Culture=neutral"), AssemblyBuilderAccess.Run); + this.ModuleBuilder = assemblyBuilder.DefineDynamicModule("StardewModdingAPI.Proxies"); + } + + /// + public TInterface CreateProxy(object instance, string sourceModID, string targetModID) + where TInterface : class + { + lock (this.Builders) + { + // validate + if (instance == null) + throw new InvalidOperationException("Can't proxy access to a null API."); + if (!typeof(TInterface).IsInterface) + throw new InvalidOperationException("The proxy type must be an interface, not a class."); + + // get proxy type + Type targetType = instance.GetType(); + string proxyTypeName = $"StardewModdingAPI.Proxies.From<{sourceModID}_{typeof(TInterface).FullName}>_To<{targetModID}_{targetType.FullName}>"; + if (!this.Builders.TryGetValue(proxyTypeName, out OriginalInterfaceProxyBuilder? builder)) + { + builder = new OriginalInterfaceProxyBuilder(proxyTypeName, this.ModuleBuilder, typeof(TInterface), targetType); + this.Builders[proxyTypeName] = builder; + } + + // create instance + return (TInterface)builder.CreateInstance(instance); + } + } + } +} -- cgit