GenericMethod.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  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. return new GenericMethod(Method, MetaUtil.ToShareTypeSigs(KlassInst), MetaUtil.ToShareTypeSigs(MethodInst));
  24. }
  25. public override bool Equals(object obj)
  26. {
  27. GenericMethod o = (GenericMethod)obj;
  28. return Method == o.Method
  29. && MetaUtil.EqualsTypeSigArray(KlassInst, o.KlassInst)
  30. && MetaUtil.EqualsTypeSigArray(MethodInst, o.MethodInst);
  31. }
  32. public override int GetHashCode()
  33. {
  34. return _hashCode;
  35. }
  36. public override string ToString()
  37. {
  38. return $"{Method}|{string.Join(",", (IEnumerable<TypeSig>)KlassInst ?? Array.Empty<TypeSig>())}|{string.Join(",", (IEnumerable<TypeSig>)MethodInst ?? Array.Empty<TypeSig>())}";
  39. }
  40. private int ComputHashCode()
  41. {
  42. int hash = MethodEqualityComparer.CompareDeclaringTypes.GetHashCode(Method);
  43. if (KlassInst != null)
  44. {
  45. hash = HashUtil.CombineHash(hash, HashUtil.ComputHash(KlassInst));
  46. }
  47. if (MethodInst != null)
  48. {
  49. hash = HashUtil.CombineHash(hash, HashUtil.ComputHash(MethodInst));
  50. }
  51. return hash;
  52. }
  53. public MethodSpec ToMethodSpec()
  54. {
  55. IMethodDefOrRef mt = KlassInst != null ?
  56. (IMethodDefOrRef)new MemberRefUser(this.Method.Module, Method.Name, Method.MethodSig, new TypeSpecUser(new GenericInstSig(this.Method.DeclaringType.ToTypeSig().ToClassOrValueTypeSig(), this.KlassInst)))
  57. : this.Method;
  58. return new MethodSpecUser(mt, new GenericInstMethodSig(MethodInst));
  59. }
  60. public static GenericMethod ResolveMethod(IMethod method, GenericArgumentContext ctx)
  61. {
  62. //Debug.Log($"== resolve method:{method}");
  63. TypeDef typeDef = null;
  64. List<TypeSig> klassInst = null;
  65. List<TypeSig> methodInst = null;
  66. MethodDef methodDef = null;
  67. var decalringType = method.DeclaringType;
  68. typeDef = decalringType.ResolveTypeDef();
  69. if (typeDef == null)
  70. {
  71. return null;
  72. }
  73. GenericInstSig gis = decalringType.TryGetGenericInstSig();
  74. if (gis != null)
  75. {
  76. klassInst = ctx != null ? gis.GenericArguments.Select(ga => MetaUtil.Inflate(ga, ctx)).ToList() : gis.GenericArguments.ToList();
  77. }
  78. methodDef = method.ResolveMethodDef();
  79. if (methodDef == null)
  80. {
  81. Debug.LogWarning($"method:{method} ResolveMethodDef() == null");
  82. return null;
  83. }
  84. if (method is MethodSpec methodSpec)
  85. {
  86. methodInst = ctx != null ? methodSpec.GenericInstMethodSig.GenericArguments.Select(ga => MetaUtil.Inflate(ga, ctx)).ToList()
  87. : methodSpec.GenericInstMethodSig.GenericArguments.ToList();
  88. }
  89. return new GenericMethod(methodDef, klassInst, methodInst);
  90. }
  91. }
  92. }