AccessCache.cs 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Reflection;
  4. namespace Harmony
  5. {
  6. public class AccessCache
  7. {
  8. Dictionary<Type, Dictionary<string, FieldInfo>> fields = new Dictionary<Type, Dictionary<string, FieldInfo>>();
  9. Dictionary<Type, Dictionary<string, PropertyInfo>> properties = new Dictionary<Type, Dictionary<string, PropertyInfo>>();
  10. readonly Dictionary<Type, Dictionary<string, Dictionary<int, MethodBase>>> methods = new Dictionary<Type, Dictionary<string, Dictionary<int, MethodBase>>>();
  11. public FieldInfo GetFieldInfo(Type type, string name)
  12. {
  13. Dictionary<string, FieldInfo> fieldsByType = null;
  14. if (fields.TryGetValue(type, out fieldsByType) == false)
  15. {
  16. fieldsByType = new Dictionary<string, FieldInfo>();
  17. fields.Add(type, fieldsByType);
  18. }
  19. FieldInfo field = null;
  20. if (fieldsByType.TryGetValue(name, out field) == false)
  21. {
  22. field = AccessTools.Field(type, name);
  23. fieldsByType.Add(name, field);
  24. }
  25. return field;
  26. }
  27. public PropertyInfo GetPropertyInfo(Type type, string name)
  28. {
  29. Dictionary<string, PropertyInfo> propertiesByType = null;
  30. if (properties.TryGetValue(type, out propertiesByType) == false)
  31. {
  32. propertiesByType = new Dictionary<string, PropertyInfo>();
  33. properties.Add(type, propertiesByType);
  34. }
  35. PropertyInfo property = null;
  36. if (propertiesByType.TryGetValue(name, out property) == false)
  37. {
  38. property = AccessTools.Property(type, name);
  39. propertiesByType.Add(name, property);
  40. }
  41. return property;
  42. }
  43. static int CombinedHashCode(IEnumerable<object> objects)
  44. {
  45. var hash1 = (5381 << 16) + 5381;
  46. var hash2 = hash1;
  47. var i = 0;
  48. foreach (var obj in objects)
  49. {
  50. if (i % 2 == 0)
  51. hash1 = ((hash1 << 5) + hash1 + (hash1 >> 27)) ^ obj.GetHashCode();
  52. else
  53. hash2 = ((hash2 << 5) + hash2 + (hash2 >> 27)) ^ obj.GetHashCode();
  54. ++i;
  55. }
  56. return hash1 + (hash2 * 1566083941);
  57. }
  58. public MethodBase GetMethodInfo(Type type, string name, Type[] arguments)
  59. {
  60. Dictionary<string, Dictionary<int, MethodBase>> methodsByName = null;
  61. methods.TryGetValue(type, out methodsByName);
  62. if (methodsByName == null)
  63. {
  64. methodsByName = new Dictionary<string, Dictionary<int, MethodBase>>();
  65. methods.Add(type, methodsByName);
  66. }
  67. Dictionary<int, MethodBase> methodsByArguments = null;
  68. methodsByName.TryGetValue(name, out methodsByArguments);
  69. if (methodsByArguments == null)
  70. {
  71. methodsByArguments = new Dictionary<int, MethodBase>();
  72. methodsByName.Add(name, methodsByArguments);
  73. }
  74. MethodBase method = null;
  75. var argumentsHash = CombinedHashCode(arguments);
  76. methodsByArguments.TryGetValue(argumentsHash, out method);
  77. if (method == null)
  78. {
  79. method = AccessTools.Method(type, name, arguments);
  80. methodsByArguments.Add(argumentsHash, method);
  81. }
  82. return method;
  83. }
  84. }
  85. }