GenericMethod.cs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. using dnlib.DotNet;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using UnityEngine;
  6. namespace HybridCLR.Editor.Meta
  7. {
  8. public class GenericMethod
  9. {
  10. public MethodDef Method { get; }
  11. public List<TypeSig> KlassInst { get; }
  12. public List<TypeSig> MethodInst { get; }
  13. private readonly int _hashCode;
  14. public GenericMethod(MethodDef method, List<TypeSig> classInst, List<TypeSig> methodInst)
  15. {
  16. Method = method;
  17. KlassInst = classInst;
  18. MethodInst = methodInst;
  19. _hashCode = ComputHashCode();
  20. }
  21. public GenericMethod ToGenericShare()
  22. {
  23. ICorLibTypes corLibTypes = Method.Module.CorLibTypes;
  24. return new GenericMethod(Method, MetaUtil.ToShareTypeSigs(corLibTypes, KlassInst), MetaUtil.ToShareTypeSigs(corLibTypes, MethodInst));
  25. }
  26. public override bool Equals(object obj)
  27. {
  28. GenericMethod o = (GenericMethod)obj;
  29. return Method == o.Method
  30. && MetaUtil.EqualsTypeSigArray(KlassInst, o.KlassInst)
  31. && MetaUtil.EqualsTypeSigArray(MethodInst, o.MethodInst);
  32. }
  33. public override int GetHashCode()
  34. {
  35. return _hashCode;
  36. }
  37. public override string ToString()
  38. {
  39. return $"{Method}|{string.Join(",", (IEnumerable<TypeSig>)KlassInst ?? Array.Empty<TypeSig>())}|{string.Join(",", (IEnumerable<TypeSig>)MethodInst ?? Array.Empty<TypeSig>())}";
  40. }
  41. private int ComputHashCode()
  42. {
  43. int hash = MethodEqualityComparer.CompareDeclaringTypes.GetHashCode(Method);
  44. if (KlassInst != null)
  45. {
  46. hash = HashUtil.CombineHash(hash, HashUtil.ComputHash(KlassInst));
  47. }
  48. if (MethodInst != null)
  49. {
  50. hash = HashUtil.CombineHash(hash, HashUtil.ComputHash(MethodInst));
  51. }
  52. return hash;
  53. }
  54. public MethodSpec ToMethodSpec()
  55. {
  56. IMethodDefOrRef mt = KlassInst != null ?
  57. (IMethodDefOrRef)new MemberRefUser(this.Method.Module, Method.Name, Method.MethodSig, new TypeSpecUser(new GenericInstSig(this.Method.DeclaringType.ToTypeSig().ToClassOrValueTypeSig(), this.KlassInst)))
  58. : this.Method;
  59. return new MethodSpecUser(mt, new GenericInstMethodSig(MethodInst));
  60. }
  61. public static GenericMethod ResolveMethod(IMethod method, GenericArgumentContext ctx)
  62. {
  63. //Debug.Log($"== resolve method:{method}");
  64. TypeDef typeDef = null;
  65. List<TypeSig> klassInst = null;
  66. List<TypeSig> methodInst = null;
  67. MethodDef methodDef = null;
  68. var decalringType = method.DeclaringType;
  69. typeDef = decalringType.ResolveTypeDef();
  70. if (typeDef == null)
  71. {
  72. return null;
  73. }
  74. GenericInstSig gis = decalringType.TryGetGenericInstSig();
  75. if (gis != null)
  76. {
  77. klassInst = ctx != null ? gis.GenericArguments.Select(ga => MetaUtil.Inflate(ga, ctx)).ToList() : gis.GenericArguments.ToList();
  78. }
  79. methodDef = method.ResolveMethodDef();
  80. if (methodDef == null)
  81. {
  82. //Debug.LogWarning($"method:{method} ResolveMethodDef() == null");
  83. return null;
  84. }
  85. if (method is MethodSpec methodSpec)
  86. {
  87. methodInst = ctx != null ? methodSpec.GenericInstMethodSig.GenericArguments.Select(ga => MetaUtil.Inflate(ga, ctx)).ToList()
  88. : methodSpec.GenericInstMethodSig.GenericArguments.ToList();
  89. }
  90. return new GenericMethod(methodDef, klassInst, methodInst);
  91. }
  92. }
  93. }