DelegateHelper.cs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  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. ArgumentNullException.ThrowIfNull(info);
  22. Type[] parameters = info.GetParameters().Select(pI => pI.ParameterType).ToArray();
  23. Type returnType = info.ReturnType;
  24. Type delegateType = GetDelegateType(parameters, returnType);
  25. return Delegate.CreateDelegate(delegateType, info);
  26. }
  27. private static Type GetDelegateType(Type[] parameters, Type returnType)
  28. {
  29. string key = GetFunctionSignatureKey(parameters, returnType);
  30. if (!_delegateTypesCache.TryGetValue(key, out Type delegateType))
  31. {
  32. delegateType = MakeDelegateType(parameters, returnType, key);
  33. _delegateTypesCache.TryAdd(key, delegateType);
  34. }
  35. return delegateType;
  36. }
  37. private static string GetFunctionSignatureKey(Type[] parameters, Type returnType)
  38. {
  39. string sig = GetTypeName(returnType);
  40. foreach (Type type in parameters)
  41. {
  42. sig += '_' + GetTypeName(type);
  43. }
  44. return sig;
  45. }
  46. private static string GetTypeName(Type type)
  47. {
  48. return type.FullName.Replace(".", string.Empty);
  49. }
  50. private const MethodAttributes CtorAttributes =
  51. MethodAttributes.RTSpecialName |
  52. MethodAttributes.HideBySig |
  53. MethodAttributes.Public;
  54. private const TypeAttributes DelegateTypeAttributes =
  55. TypeAttributes.Class |
  56. TypeAttributes.Public |
  57. TypeAttributes.Sealed |
  58. TypeAttributes.AnsiClass |
  59. TypeAttributes.AutoClass;
  60. private const MethodImplAttributes ImplAttributes =
  61. MethodImplAttributes.Runtime |
  62. MethodImplAttributes.Managed;
  63. private const MethodAttributes InvokeAttributes =
  64. MethodAttributes.Public |
  65. MethodAttributes.HideBySig |
  66. MethodAttributes.NewSlot |
  67. MethodAttributes.Virtual;
  68. private static readonly Type[] _delegateCtorSignature = { typeof(object), typeof(IntPtr) };
  69. private static Type MakeDelegateType(Type[] parameters, Type returnType, string name)
  70. {
  71. TypeBuilder builder = _modBuilder.DefineType(name, DelegateTypeAttributes, typeof(MulticastDelegate));
  72. builder.DefineConstructor(CtorAttributes, CallingConventions.Standard, _delegateCtorSignature).SetImplementationFlags(ImplAttributes);
  73. builder.DefineMethod("Invoke", InvokeAttributes, returnType, parameters).SetImplementationFlags(ImplAttributes);
  74. return builder.CreateTypeInfo();
  75. }
  76. }
  77. }