104 lines
		
	
	
	
		
			3.5 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			104 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)
 | |
|         {
 | |
|             ArgumentNullException.ThrowIfNull(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();
 | |
|         }
 | |
|     }
 | |
| }
 | 
