File: System\Runtime\InteropServices\ComAwareEventInfo.cs
Project: ndp\fx\src\Core\System.Core.csproj (System.Core)
using System;
using System.Security.Permissions;
 
namespace System.Runtime.InteropServices {
 
 
    [System.Security.SecuritySafeCritical]
    public class ComAwareEventInfo : System.Reflection.EventInfo {
 
        #region private fields
        private System.Reflection.EventInfo _innerEventInfo;
        #endregion
 
        #region ctor
        public ComAwareEventInfo(Type type, string eventName) {
            _innerEventInfo = type.GetEvent(eventName);
        }
        #endregion
 
        #region protected overrides
#if FEATURE_NETCORE
        [System.Security.SecuritySafeCritical]
#endif//FEATURE_NETCORE
        public override void AddEventHandler(object target, Delegate handler) {
            if (Marshal.IsComObject(target)) {
                // retrieve sourceIid and dispid
                Guid sourceIid;
                int dispid;
                GetDataForComInvocation(_innerEventInfo, out sourceIid, out dispid);
 
#if FEATURE_CAS_POLICY
                // now validate the caller can call into native and redirect to ComEventHelpers.Combine
                SecurityPermission perm = new SecurityPermission(SecurityPermissionFlag.UnmanagedCode);
                perm.Demand();
#endif//FEATURE_CAS_POLICY
                System.Runtime.InteropServices.ComEventsHelper.Combine(target, sourceIid, dispid, handler);
            } else {
                // we are dealing with a managed object - just add the delegate through reflection
                _innerEventInfo.AddEventHandler(target, handler);
            }
        }
 
#if FEATURE_NETCORE
        [System.Security.SecuritySafeCritical]
#endif//FEATURE_NETCORE
        public override void RemoveEventHandler(object target, Delegate handler) {
            if (Marshal.IsComObject(target)) {
                // retrieve sourceIid and dispid
                Guid sourceIid;
                int dispid;
                GetDataForComInvocation(_innerEventInfo, out sourceIid, out dispid);
 
#if FEATURE_CAS_POLICY
                // now validate the caller can call into native and redirect to ComEventHelpers.Combine
                SecurityPermission perm = new SecurityPermission(SecurityPermissionFlag.UnmanagedCode);
                perm.Demand();
#endif//FEATURE_CAS_POLICY
                System.Runtime.InteropServices.ComEventsHelper.Remove(target, sourceIid, dispid, handler);
            } else {
                // we are dealing with a managed object - just add the delegate through relection
                _innerEventInfo.RemoveEventHandler(target, handler);
            }
        }
        #endregion
 
        #region public overrides
        public override System.Reflection.EventAttributes Attributes {
            get { return _innerEventInfo.Attributes; }
        }
 
        public override System.Reflection.MethodInfo GetAddMethod(bool nonPublic) {
            return _innerEventInfo.GetAddMethod(nonPublic);
        }
 
        public override System.Reflection.MethodInfo GetRaiseMethod(bool nonPublic) {
            return _innerEventInfo.GetRaiseMethod(nonPublic);
        }
 
        public override System.Reflection.MethodInfo GetRemoveMethod(bool nonPublic) {
            return _innerEventInfo.GetRemoveMethod(nonPublic);
        }
 
        public override Type DeclaringType {
            get { return _innerEventInfo.DeclaringType; }
        }
 
        public override object[] GetCustomAttributes(Type attributeType, bool inherit) {
            return _innerEventInfo.GetCustomAttributes(attributeType, inherit);
        }
 
        public override object[] GetCustomAttributes(bool inherit) {
            return _innerEventInfo.GetCustomAttributes(inherit);
        }
 
        public override bool IsDefined(Type attributeType, bool inherit) {
            return _innerEventInfo.IsDefined(attributeType, inherit);
        }
 
        public override string Name {
            get { return _innerEventInfo.Name; }
        }
 
        public override Type ReflectedType {
            get { return _innerEventInfo.ReflectedType; }
        }
        #endregion
 
        #region private methods
 
        private static void GetDataForComInvocation(System.Reflection.EventInfo eventInfo, out Guid sourceIid, out int dispid) {
            object[] comEventInterfaces = eventInfo.DeclaringType.GetCustomAttributes(typeof(ComEventInterfaceAttribute), false);
 
            if (comEventInterfaces == null || comEventInterfaces.Length == 0) {
                // 
                throw new InvalidOperationException("event invocation for COM objects requires interface to be attributed with ComSourceInterfaceGuidAttribute");
            }
 
            if (comEventInterfaces.Length > 1) {
                // 
                throw new System.Reflection.AmbiguousMatchException("more than one ComSourceInterfaceGuidAttribute found");
            }
 
            Type sourceItf = ((ComEventInterfaceAttribute)comEventInterfaces[0]).SourceInterface;
            Guid guid = sourceItf.GUID;
 
            System.Reflection.MethodInfo methodInfo = sourceItf.GetMethod(eventInfo.Name);
            Attribute dispIdAttribute = Attribute.GetCustomAttribute(methodInfo, typeof(DispIdAttribute));
            if (dispIdAttribute == null) {
                // 
                throw new InvalidOperationException("event invocation for COM objects requires event to be attributed with DispIdAttribute");
            }
 
            sourceIid = guid;
            dispid = ((DispIdAttribute)dispIdAttribute).Value;
        }
        #endregion
    }
}