108 lines
3.5 KiB
C#
108 lines
3.5 KiB
C#
|
using System;
|
||
|
using System.Collections.Generic;
|
||
|
using System.Linq;
|
||
|
using System.Reflection;
|
||
|
using System.Reflection.Emit;
|
||
|
|
||
|
namespace ARMeilleure.Translation
|
||
|
{
|
||
|
static class DelegateHelper
|
||
|
{
|
||
|
private const string DelegateTypesAssemblyName = "JitDelegateTypes";
|
||
|
|
||
|
private static readonly ModuleBuilder _modBuilder;
|
||
|
|
||
|
private static readonly Dictionary<string, Type> _delegateTypesCache;
|
||
|
|
||
|
static DelegateHelper()
|
||
|
{
|
||
|
AssemblyBuilder asmBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(DelegateTypesAssemblyName), AssemblyBuilderAccess.Run);
|
||
|
|
||
|
_modBuilder = asmBuilder.DefineDynamicModule(DelegateTypesAssemblyName);
|
||
|
|
||
|
_delegateTypesCache = new Dictionary<string, Type>();
|
||
|
}
|
||
|
|
||
|
public static Delegate GetDelegate(MethodInfo info)
|
||
|
{
|
||
|
if (info == null)
|
||
|
{
|
||
|
throw new ArgumentNullException(nameof(info));
|
||
|
}
|
||
|
|
||
|
Type[] parameters = info.GetParameters().Select(pI => pI.ParameterType).ToArray();
|
||
|
Type returnType = info.ReturnType;
|
||
|
|
||
|
Type delegateType = GetDelegateType(parameters, returnType);
|
||
|
|
||
|
return Delegate.CreateDelegate(delegateType, info);
|
||
|
}
|
||
|
|
||
|
private static Type GetDelegateType(Type[] parameters, Type returnType)
|
||
|
{
|
||
|
string key = GetFunctionSignatureKey(parameters, returnType);
|
||
|
|
||
|
if (!_delegateTypesCache.TryGetValue(key, out Type delegateType))
|
||
|
{
|
||
|
delegateType = MakeDelegateType(parameters, returnType, key);
|
||
|
|
||
|
_delegateTypesCache.TryAdd(key, delegateType);
|
||
|
}
|
||
|
|
||
|
return delegateType;
|
||
|
}
|
||
|
|
||
|
private static string GetFunctionSignatureKey(Type[] parameters, Type returnType)
|
||
|
{
|
||
|
string sig = GetTypeName(returnType);
|
||
|
|
||
|
foreach (Type type in parameters)
|
||
|
{
|
||
|
sig += '_' + GetTypeName(type);
|
||
|
}
|
||
|
|
||
|
return sig;
|
||
|
}
|
||
|
|
||
|
private static string GetTypeName(Type type)
|
||
|
{
|
||
|
return type.FullName.Replace(".", string.Empty);
|
||
|
}
|
||
|
|
||
|
private const MethodAttributes CtorAttributes =
|
||
|
MethodAttributes.RTSpecialName |
|
||
|
MethodAttributes.HideBySig |
|
||
|
MethodAttributes.Public;
|
||
|
|
||
|
private const TypeAttributes DelegateTypeAttributes =
|
||
|
TypeAttributes.Class |
|
||
|
TypeAttributes.Public |
|
||
|
TypeAttributes.Sealed |
|
||
|
TypeAttributes.AnsiClass |
|
||
|
TypeAttributes.AutoClass;
|
||
|
|
||
|
private const MethodImplAttributes ImplAttributes =
|
||
|
MethodImplAttributes.Runtime |
|
||
|
MethodImplAttributes.Managed;
|
||
|
|
||
|
private const MethodAttributes InvokeAttributes =
|
||
|
MethodAttributes.Public |
|
||
|
MethodAttributes.HideBySig |
|
||
|
MethodAttributes.NewSlot |
|
||
|
MethodAttributes.Virtual;
|
||
|
|
||
|
private static readonly Type[] _delegateCtorSignature = { typeof(object), typeof(IntPtr) };
|
||
|
|
||
|
private static Type MakeDelegateType(Type[] parameters, Type returnType, string name)
|
||
|
{
|
||
|
TypeBuilder builder = _modBuilder.DefineType(name, DelegateTypeAttributes, typeof(MulticastDelegate));
|
||
|
|
||
|
builder.DefineConstructor(CtorAttributes, CallingConventions.Standard, _delegateCtorSignature).SetImplementationFlags(ImplAttributes);
|
||
|
|
||
|
builder.DefineMethod("Invoke", InvokeAttributes, returnType, parameters).SetImplementationFlags(ImplAttributes);
|
||
|
|
||
|
return builder.CreateTypeInfo();
|
||
|
}
|
||
|
}
|
||
|
}
|