ProxyData.cs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. using System.Reflection;
  2. using System.Collections.Generic;
  3. using System;
  4. namespace com.bbbirder.injection
  5. {
  6. public interface IProxyData : IInjection
  7. {
  8. }
  9. public abstract class ProxyData : IProxyData
  10. {
  11. static readonly BindingFlags bindingFlags = 0
  12. | BindingFlags.Instance
  13. | BindingFlags.NonPublic
  14. | BindingFlags.Public
  15. | BindingFlags.DeclaredOnly
  16. ;
  17. // static bool m_IsFixed {get;set;}
  18. static Dictionary<Type, Dictionary<string, Delegate>> s_AllGetters = new();
  19. static Dictionary<Type, Dictionary<string, Delegate>> s_AllSetters = new();
  20. protected Dictionary<string, Delegate> getters
  21. {
  22. get
  23. {
  24. var type = GetType();
  25. if (!s_AllGetters.TryGetValue(type, out var result))
  26. {
  27. result = s_AllGetters[type] = new();
  28. }
  29. return result;
  30. }
  31. }
  32. protected Dictionary<string, Delegate> setters
  33. {
  34. get
  35. {
  36. var type = GetType();
  37. if (!s_AllSetters.TryGetValue(type, out var result))
  38. {
  39. result = s_AllSetters[type] = new();
  40. }
  41. return result;
  42. }
  43. }
  44. public Action<string> OnSetProperty { get; set; }
  45. public Action<string> OnGetProperty { get; set; }
  46. Func<C, T> ProxyGet<C, T>(string name) where C : ProxyData
  47. {
  48. return o =>
  49. {
  50. // DebugHelper.Log("get " + name);
  51. o.OnGetProperty?.Invoke(name);
  52. var getter = o.getters[name];
  53. var method = getter as Func<C, T>;
  54. return method.Invoke(o);
  55. };
  56. }
  57. Action<C, T> ProxySet<C, T>(string name) where C : ProxyData
  58. {
  59. return (o, v) =>
  60. {
  61. var setter = o.setters[name];
  62. var method = setter as Action<C, T>;
  63. method.Invoke(o, v);
  64. // DebugHelper.Log("set " + name + "=" + v);
  65. o.OnSetProperty?.Invoke(name);
  66. };
  67. }
  68. /// <summary>
  69. /// whether this type of data is properly injected and fixed
  70. /// </summary>
  71. /// <returns></returns>
  72. public bool IsFixed(){
  73. // DebugHelper.Log(m_IsFixed);
  74. return FixHelper.IsInjected(GetType());
  75. }
  76. public IEnumerable<InjectionInfo> ProvideInjections()
  77. {
  78. var targetType = this.GetType();
  79. if (targetType.IsAbstract || targetType.IsInterface)
  80. yield break;
  81. var proxyGet = typeof(ProxyData).GetMethod(nameof(ProxyGet), bindingFlags);
  82. var proxySet = typeof(ProxyData).GetMethod(nameof(ProxySet), bindingFlags);
  83. var instMethod = default(MethodInfo);
  84. var nameArgs = new string[1];
  85. foreach (var property in targetType.GetProperties(bindingFlags))
  86. {
  87. var name = property.Name;
  88. nameArgs[0] = name;
  89. instMethod = proxyGet.MakeGenericMethod(targetType, property.PropertyType);
  90. if (property.GetMethod != null)
  91. {
  92. yield return InjectionInfo.Create(
  93. property.GetMethod,
  94. instMethod.Invoke(this, nameArgs) as Delegate,
  95. f =>
  96. {
  97. // m_IsFixed = true;
  98. getters[name] = f;
  99. }
  100. );
  101. }
  102. instMethod = proxySet.MakeGenericMethod(targetType, property.PropertyType);
  103. if (property.SetMethod != null)
  104. {
  105. yield return InjectionInfo.Create(
  106. property.SetMethod,
  107. instMethod.Invoke(this, nameArgs) as Delegate,
  108. f =>
  109. {
  110. // m_IsFixed = true;
  111. setters[name] = f;
  112. }
  113. );
  114. }
  115. }
  116. }
  117. }
  118. }