Mirror of Svelto.ECS because we're a fan of it
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

WeakActionStruct.cs 4.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. using System;
  2. using System.Reflection;
  3. using System.Runtime.InteropServices;
  4. using Svelto.Utilities;
  5. //careful, you must handle the destruction of the GCHandles!
  6. namespace Svelto.WeakEvents
  7. {
  8. public struct WeakActionStruct<T1, T2> : IEquatable<WeakActionStruct<T1, T2>>, IDisposable
  9. {
  10. public WeakActionStruct(Action<T1, T2> listener)
  11. {
  12. WeakActionStructUtility.Init(listener.Target, listener.GetMethodInfoEx(), out _objectRef, out _method);
  13. }
  14. public bool Invoke(object[] args)
  15. {
  16. return WeakActionStructUtility.Invoke(ref _objectRef, _method, args);
  17. }
  18. public bool Equals(WeakActionStruct<T1, T2> other)
  19. {
  20. return WeakActionStructUtility.IsMatch(_objectRef.Target, _method,
  21. other._objectRef.Target, other._method);
  22. }
  23. public void Dispose()
  24. {
  25. _objectRef.Free();
  26. }
  27. public bool IsMatch(object otherObject, MethodInfo otherMethod)
  28. {
  29. return WeakActionStructUtility.IsMatch(_objectRef.Target, _method,
  30. otherObject, otherMethod);
  31. }
  32. GCHandle _objectRef;
  33. readonly MethodInfo _method;
  34. }
  35. public struct WeakActionStruct<T> : IEquatable<WeakActionStruct<T>>, IDisposable
  36. {
  37. public WeakActionStruct(Action<T> listener)
  38. {
  39. WeakActionStructUtility.Init(listener.Target, listener.GetMethodInfoEx(),
  40. out _objectRef, out _method);
  41. }
  42. public bool Invoke(object[] args)
  43. {
  44. return WeakActionStructUtility.Invoke(ref _objectRef, _method, args);
  45. }
  46. public bool Equals(WeakActionStruct<T> other)
  47. {
  48. return WeakActionStructUtility.IsMatch(_objectRef.Target, _method,
  49. other._objectRef.Target, other._method);
  50. }
  51. public void Dispose()
  52. {
  53. _objectRef.Free();
  54. }
  55. public bool IsMatch(object otherObject, MethodInfo otherMethod)
  56. {
  57. return WeakActionStructUtility.IsMatch(_objectRef.Target, _method,
  58. otherObject, otherMethod);
  59. }
  60. GCHandle _objectRef;
  61. readonly MethodInfo _method;
  62. }
  63. public struct WeakActionStruct : IEquatable<WeakActionStruct>, IDisposable
  64. {
  65. public WeakActionStruct(Action listener)
  66. {
  67. WeakActionStructUtility.Init(listener.Target, listener.GetMethodInfoEx(),
  68. out _objectRef, out _method);
  69. }
  70. public bool Invoke()
  71. {
  72. return WeakActionStructUtility.Invoke(ref _objectRef, _method, null);
  73. }
  74. public bool Equals(WeakActionStruct other)
  75. {
  76. return WeakActionStructUtility.IsMatch(_objectRef.Target, _method,
  77. other._objectRef.Target, other._method);
  78. }
  79. public void Dispose()
  80. {
  81. _objectRef.Free();
  82. }
  83. public bool IsMatch(object otherObject, MethodInfo otherMethod)
  84. {
  85. return WeakActionStructUtility.IsMatch(_objectRef.Target, _method,
  86. otherObject, otherMethod);
  87. }
  88. GCHandle _objectRef;
  89. readonly MethodInfo _method;
  90. }
  91. static class WeakActionStructUtility
  92. {
  93. internal static void Init(object target, MethodInfo method,
  94. out GCHandle objectRef, out MethodInfo methodOut)
  95. {
  96. objectRef = GCHandle.Alloc(target, GCHandleType.Weak);
  97. methodOut = method;
  98. #if DEBUG && !PROFILER
  99. if (method.IsCompilerGenerated() == true)
  100. throw new ArgumentException("Cannot create weak event to anonymous method with closure.");
  101. #endif
  102. }
  103. public static bool Invoke(ref GCHandle objectRef, MethodInfo method, object[] args)
  104. {
  105. if (objectRef.IsAllocated && objectRef.Target != null)
  106. {
  107. method.Invoke(objectRef.Target, args);
  108. return true;
  109. }
  110. Dispose(ref objectRef);
  111. return false;
  112. }
  113. public static void Dispose(ref GCHandle objectRef)
  114. {
  115. objectRef.Free();
  116. }
  117. public static bool IsMatch(object objectRef, MethodInfo method,
  118. object _objectRef, MethodInfo _method)
  119. {
  120. return _method.Equals(method) && objectRef.Equals(_objectRef);
  121. }
  122. }
  123. }