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.

148 lines
4.4KB

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