EventInfo.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT license.
  3. // See the LICENSE file in the project root for more information.
  4. using System.Diagnostics;
  5. using System.Runtime.CompilerServices;
  6. #if FEATURE_COMINTEROP
  7. using EventRegistrationToken = System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken;
  8. #endif //#if FEATURE_COMINTEROP
  9. namespace System.Reflection
  10. {
  11. public abstract class EventInfo : MemberInfo
  12. {
  13. protected EventInfo() { }
  14. public override MemberTypes MemberType => MemberTypes.Event;
  15. public abstract EventAttributes Attributes { get; }
  16. public bool IsSpecialName => (Attributes & EventAttributes.SpecialName) != 0;
  17. public MethodInfo[] GetOtherMethods() => GetOtherMethods(nonPublic: false);
  18. public virtual MethodInfo[] GetOtherMethods(bool nonPublic) { throw NotImplemented.ByDesign; }
  19. public virtual MethodInfo AddMethod => GetAddMethod(nonPublic: true);
  20. public virtual MethodInfo RemoveMethod => GetRemoveMethod(nonPublic: true);
  21. public virtual MethodInfo RaiseMethod => GetRaiseMethod(nonPublic: true);
  22. public MethodInfo GetAddMethod() => GetAddMethod(nonPublic: false);
  23. public MethodInfo GetRemoveMethod() => GetRemoveMethod(nonPublic: false);
  24. public MethodInfo GetRaiseMethod() => GetRaiseMethod(nonPublic: false);
  25. public abstract MethodInfo GetAddMethod(bool nonPublic);
  26. public abstract MethodInfo GetRemoveMethod(bool nonPublic);
  27. public abstract MethodInfo GetRaiseMethod(bool nonPublic);
  28. public virtual bool IsMulticast
  29. {
  30. get
  31. {
  32. Type cl = EventHandlerType;
  33. Type mc = typeof(MulticastDelegate);
  34. return mc.IsAssignableFrom(cl);
  35. }
  36. }
  37. public virtual Type EventHandlerType
  38. {
  39. get
  40. {
  41. MethodInfo m = GetAddMethod(true);
  42. ParameterInfo[] p = m.GetParametersNoCopy();
  43. Type del = typeof(Delegate);
  44. for (int i = 0; i < p.Length; i++)
  45. {
  46. Type c = p[i].ParameterType;
  47. if (c.IsSubclassOf(del))
  48. return c;
  49. }
  50. return null;
  51. }
  52. }
  53. [DebuggerHidden]
  54. [DebuggerStepThrough]
  55. public virtual void AddEventHandler(object target, Delegate handler)
  56. {
  57. MethodInfo addMethod = GetAddMethod(nonPublic: false);
  58. if (addMethod == null)
  59. throw new InvalidOperationException(SR.InvalidOperation_NoPublicAddMethod);
  60. #if FEATURE_COMINTEROP
  61. if (addMethod.ReturnType == typeof(EventRegistrationToken))
  62. throw new InvalidOperationException(SR.InvalidOperation_NotSupportedOnWinRTEvent);
  63. #endif //#if FEATURE_COMINTEROP
  64. addMethod.Invoke(target, new object[] { handler });
  65. }
  66. [DebuggerHidden]
  67. [DebuggerStepThrough]
  68. public virtual void RemoveEventHandler(object target, Delegate handler)
  69. {
  70. MethodInfo removeMethod = GetRemoveMethod(nonPublic: false);
  71. if (removeMethod == null)
  72. throw new InvalidOperationException(SR.InvalidOperation_NoPublicRemoveMethod);
  73. #if FEATURE_COMINTEROP
  74. ParameterInfo[] parameters = removeMethod.GetParametersNoCopy();
  75. if (parameters[0].ParameterType == typeof(EventRegistrationToken))
  76. throw new InvalidOperationException(SR.InvalidOperation_NotSupportedOnWinRTEvent);
  77. #endif //#if FEATURE_COMINTEROP
  78. removeMethod.Invoke(target, new object[] { handler });
  79. }
  80. public override bool Equals(object obj) => base.Equals(obj);
  81. public override int GetHashCode() => base.GetHashCode();
  82. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  83. public static bool operator ==(EventInfo left, EventInfo right)
  84. {
  85. // Test "right" first to allow branch elimination when inlined for null checks (== null)
  86. // so it can become a simple test
  87. if (right is null)
  88. {
  89. // return true/false not the test result https://github.com/dotnet/coreclr/issues/914
  90. return (left is null) ? true : false;
  91. }
  92. // Try fast reference equality and opposite null check prior to calling the slower virtual Equals
  93. if ((object)left == (object)right)
  94. {
  95. return true;
  96. }
  97. return (left is null) ? false : left.Equals(right);
  98. }
  99. public static bool operator !=(EventInfo left, EventInfo right) => !(left == right);
  100. }
  101. }