File: src\libraries\System.Private.CoreLib\src\System\Reflection\EventInfo.cs
Web Access
Project: src\src\coreclr\System.Private.CoreLib\System.Private.CoreLib.csproj (System.Private.CoreLib)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Diagnostics;
using System.Runtime.CompilerServices;
 
namespace System.Reflection
{
    public abstract class EventInfo : MemberInfo
    {
        protected EventInfo() { }
 
        public override MemberTypes MemberType => MemberTypes.Event;
 
        public abstract EventAttributes Attributes { get; }
        public bool IsSpecialName => (Attributes & EventAttributes.SpecialName) != 0;
 
        public MethodInfo[] GetOtherMethods() => GetOtherMethods(nonPublic: false);
        public virtual MethodInfo[] GetOtherMethods(bool nonPublic) { throw NotImplemented.ByDesign; }
 
        public virtual MethodInfo? AddMethod => GetAddMethod(nonPublic: true);
        public virtual MethodInfo? RemoveMethod => GetRemoveMethod(nonPublic: true);
        public virtual MethodInfo? RaiseMethod => GetRaiseMethod(nonPublic: true);
 
        public MethodInfo? GetAddMethod() => GetAddMethod(nonPublic: false);
        public MethodInfo? GetRemoveMethod() => GetRemoveMethod(nonPublic: false);
        public MethodInfo? GetRaiseMethod() => GetRaiseMethod(nonPublic: false);
 
        public abstract MethodInfo? GetAddMethod(bool nonPublic);
        public abstract MethodInfo? GetRemoveMethod(bool nonPublic);
        public abstract MethodInfo? GetRaiseMethod(bool nonPublic);
 
        public virtual bool IsMulticast
        {
            get
            {
                Type? cl = EventHandlerType;
                Type mc = typeof(MulticastDelegate);
                return mc.IsAssignableFrom(cl);
            }
        }
 
        public virtual Type? EventHandlerType
        {
            get
            {
                MethodInfo m = GetAddMethod(true)!;
                ReadOnlySpan<ParameterInfo> p = m.GetParametersAsSpan();
                Type del = typeof(Delegate);
                for (int i = 0; i < p.Length; i++)
                {
                    Type c = p[i].ParameterType;
                    if (c.IsSubclassOf(del))
                        return c;
                }
                return null;
            }
        }
 
        [DebuggerHidden]
        [DebuggerStepThrough]
        public virtual void AddEventHandler(object? target, Delegate? handler)
        {
            MethodInfo addMethod = GetAddMethod(nonPublic: false) ?? throw new InvalidOperationException(SR.InvalidOperation_NoPublicAddMethod);
            addMethod.Invoke(target, [handler]);
        }
 
        [DebuggerHidden]
        [DebuggerStepThrough]
        public virtual void RemoveEventHandler(object? target, Delegate? handler)
        {
            MethodInfo removeMethod = GetRemoveMethod(nonPublic: false) ?? throw new InvalidOperationException(SR.InvalidOperation_NoPublicRemoveMethod);
            removeMethod.Invoke(target, [handler]);
        }
 
        public override bool Equals(object? obj) => base.Equals(obj);
        public override int GetHashCode() => base.GetHashCode();
 
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool operator ==(EventInfo? left, EventInfo? right)
        {
            // Test "right" first to allow branch elimination when inlined for null checks (== null)
            // so it can become a simple test
            if (right is null)
            {
                return left is null;
            }
 
            // Try fast reference equality and opposite null check prior to calling the slower virtual Equals
            if (ReferenceEquals(left, right))
            {
                return true;
            }
 
            return left is not null && left.Equals(right);
        }
 
        public static bool operator !=(EventInfo? left, EventInfo? right) => !(left == right);
    }
}