DelegateHelper.cs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Reflection;
  5. using System.Reflection.Emit;
  6. namespace ARMeilleure.Translation
  7. {
  8. static class DelegateHelper
  9. {
  10. private const string DelegateTypesAssemblyName = "JitDelegateTypes";
  11. private static readonly ModuleBuilder _modBuilder;
  12. private static readonly Dictionary<string, Type> _delegateTypesCache;
  13. static DelegateHelper()
  14. {
  15. AssemblyBuilder asmBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(DelegateTypesAssemblyName), AssemblyBuilderAccess.Run);
  16. _modBuilder = asmBuilder.DefineDynamicModule(DelegateTypesAssemblyName);
  17. _delegateTypesCache = new Dictionary<string, Type>();
  18. }
  19. public static Delegate GetDelegate(MethodInfo info)
  20. {
  21. if (info == null)
  22. {
  23. throw new ArgumentNullException(nameof(info));
  24. }
  25. Type[] parameters = info.GetParameters().Select(pI => pI.ParameterType).ToArray();
  26. Type returnType = info.ReturnType;
  27. Type delegateType = GetDelegateType(parameters, returnType);
  28. return Delegate.CreateDelegate(delegateType, info);
  29. }
  30. private static Type GetDelegateType(Type[] parameters, Type returnType)
  31. {
  32. string key = GetFunctionSignatureKey(parameters, returnType);
  33. if (!_delegateTypesCache.TryGetValue(key, out Type delegateType))
  34. {
  35. delegateType = MakeDelegateType(parameters, returnType, key);
  36. _delegateTypesCache.TryAdd(key, delegateType);
  37. }
  38. return delegateType;
  39. }
  40. private static string GetFunctionSignatureKey(Type[] parameters, Type returnType)
  41. {
  42. string sig = GetTypeName(returnType);
  43. foreach (Type type in parameters)
  44. {
  45. sig += '_' + GetTypeName(type);
  46. }
  47. return sig;
  48. }
  49. private static string GetTypeName(Type type)
  50. {
  51. return type.FullName.Replace(".", string.Empty);
  52. }
  53. private const MethodAttributes CtorAttributes =
  54. MethodAttributes.RTSpecialName |
  55. MethodAttributes.HideBySig |
  56. MethodAttributes.Public;
  57. private const TypeAttributes DelegateTypeAttributes =
  58. TypeAttributes.Class |
  59. TypeAttributes.Public |
  60. TypeAttributes.Sealed |
  61. TypeAttributes.AnsiClass |
  62. TypeAttributes.AutoClass;
  63. private const MethodImplAttributes ImplAttributes =
  64. MethodImplAttributes.Runtime |
  65. MethodImplAttributes.Managed;
  66. private const MethodAttributes InvokeAttributes =
  67. MethodAttributes.Public |
  68. MethodAttributes.HideBySig |
  69. MethodAttributes.NewSlot |
  70. MethodAttributes.Virtual;
  71. private static readonly Type[] _delegateCtorSignature = { typeof(object), typeof(IntPtr) };
  72. private static Type MakeDelegateType(Type[] parameters, Type returnType, string name)
  73. {
  74. TypeBuilder builder = _modBuilder.DefineType(name, DelegateTypeAttributes, typeof(MulticastDelegate));
  75. builder.DefineConstructor(CtorAttributes, CallingConventions.Standard, _delegateCtorSignature).SetImplementationFlags(ImplAttributes);
  76. builder.DefineMethod("Invoke", InvokeAttributes, returnType, parameters).SetImplementationFlags(ImplAttributes);
  77. return builder.CreateTypeInfo();
  78. }
  79. }
  80. }