2 // System.Reflection/EventInfo.cs
5 // Paolo Molaro (lupus@ximian.com)
7 // (C) 2001 Ximian, Inc. http://www.ximian.com
8 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System.Diagnostics;
31 using System.Runtime.InteropServices;
33 namespace System.Reflection {
36 [ComDefaultInterfaceAttribute (typeof (_EventInfo))]
38 [ClassInterface(ClassInterfaceType.None)]
39 [StructLayout (LayoutKind.Sequential)]
40 public abstract class EventInfo : MemberInfo, _EventInfo {
41 AddEventAdapter cached_add_event;
43 public abstract EventAttributes Attributes {get;}
46 #if NET_4_0 || MOONLIGHT
49 Type EventHandlerType {
52 MethodInfo add = GetAddMethod (true);
53 p = add.GetParameters ();
55 Type t = p [0].ParameterType;
56 /* is it alwasys the first arg?
57 if (!t.IsSubclassOf (typeof (System.Delegate)))
58 throw new Exception ("no delegate in event");*/
66 #if NET_4_0 || MOONLIGHT
69 bool IsMulticast {get {return true;}}
70 public bool IsSpecialName {get {return (Attributes & EventAttributes.SpecialName ) != 0;}}
71 public override MemberTypes MemberType {
72 get {return MemberTypes.Event;}
75 protected EventInfo() {
82 #if NET_4_0 || MOONLIGHT
85 void AddEventHandler (object target, Delegate handler)
87 if (cached_add_event == null) {
88 MethodInfo add = GetAddMethod ();
90 throw new InvalidOperationException ("Cannot add a handler to an event that doesn't have a visible add method");
91 if (add.DeclaringType.IsValueType) {
92 if (target == null && !add.IsStatic)
93 throw new TargetException ("Cannot add a handler to a non static event with a null target");
94 add.Invoke (target, new object [] {handler});
97 cached_add_event = CreateAddEventDelegate (add);
99 //if (target == null && is_instance)
100 // throw new TargetException ("Cannot add a handler to a non static event with a null target");
101 cached_add_event (target, handler);
104 public MethodInfo GetAddMethod() {
105 return GetAddMethod (false);
107 public abstract MethodInfo GetAddMethod(bool nonPublic);
108 public MethodInfo GetRaiseMethod() {
109 return GetRaiseMethod (false);
111 public abstract MethodInfo GetRaiseMethod( bool nonPublic);
112 public MethodInfo GetRemoveMethod() {
113 return GetRemoveMethod (false);
115 public abstract MethodInfo GetRemoveMethod( bool nonPublic);
117 public virtual MethodInfo[] GetOtherMethods (bool nonPublic) {
118 // implemented by the derived class
119 return new MethodInfo [0];
122 public MethodInfo[] GetOtherMethods () {
123 return GetOtherMethods (false);
127 [DebuggerStepThrough]
129 #if NET_4_0 || MOONLIGHT
132 void RemoveEventHandler (object target, Delegate handler)
134 MethodInfo remove = GetRemoveMethod ();
136 throw new InvalidOperationException ("Cannot remove a handler to an event that doesn't have a visible remove method");
138 remove.Invoke (target, new object [] {handler});
142 public override bool Equals (object obj)
144 return obj == (object) this;
147 public override int GetHashCode ()
149 return base.GetHashCode ();
152 public static bool operator == (EventInfo left, EventInfo right)
154 if ((object)left == (object)right)
156 if ((object)left == null ^ (object)right == null)
158 return left.Equals (right);
161 public static bool operator != (EventInfo left, EventInfo right)
163 if ((object)left == (object)right)
165 if ((object)left == null ^ (object)right == null)
167 return !left.Equals (right);
171 void _EventInfo.GetIDsOfNames ([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
173 throw new NotImplementedException ();
176 void _EventInfo.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
178 throw new NotImplementedException ();
181 void _EventInfo.GetTypeInfoCount (out uint pcTInfo)
183 throw new NotImplementedException ();
186 void _EventInfo.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
188 throw new NotImplementedException ();
190 delegate void AddEventAdapter (object _this, Delegate dele);
191 delegate void AddEvent<T, D> (T _this, D dele);
192 delegate void StaticAddEvent<D> (D dele);
194 #pragma warning disable 169
195 // Used via reflection
196 static void AddEventFrame<T,D> (AddEvent<T,D> addEvent, object obj, object dele)
199 throw new TargetException ("Cannot add a handler to a non static event with a null target");
201 throw new TargetException ("Object doesn't match target");
202 addEvent ((T)obj, (D)dele);
205 static void StaticAddEventAdapterFrame<D> (StaticAddEvent<D> addEvent, object obj, object dele)
209 #pragma warning restore 169
212 * The idea behing this optimization is to use a pair of delegates to simulate the same effect of doing a reflection call.
213 * The first delegate performs casting and boxing, the second dispatch to the add_... method.
215 static AddEventAdapter CreateAddEventDelegate (MethodInfo method)
219 object addHandlerDelegate;
220 MethodInfo adapterFrame;
221 Type addHandlerDelegateType;
224 if (method.IsStatic) {
225 typeVector = new Type[] { method.GetParameters () [0].ParameterType };
226 addHandlerDelegateType = typeof (StaticAddEvent<>);
227 frameName = "StaticAddEventAdapterFrame";
229 typeVector = new Type[] { method.DeclaringType, method.GetParameters () [0].ParameterType };
230 addHandlerDelegateType = typeof (AddEvent<,>);
231 frameName = "AddEventFrame";
234 addHandlerType = addHandlerDelegateType.MakeGenericType (typeVector);
236 // with Silverlight a coreclr failure (e.g. Transparent caller creating a delegate on a Critical method)
237 // would normally throw an ArgumentException, so we set throwOnBindFailure to false and check for a null
238 // delegate that we can transform into a MethodAccessException
239 addHandlerDelegate = Delegate.CreateDelegate (addHandlerType, method, false);
240 if (addHandlerDelegate == null)
241 throw new MethodAccessException ();
243 addHandlerDelegate = Delegate.CreateDelegate (addHandlerType, method);
245 adapterFrame = typeof (EventInfo).GetMethod (frameName, BindingFlags.Static | BindingFlags.NonPublic);
246 adapterFrame = adapterFrame.MakeGenericMethod (typeVector);
247 return (AddEventAdapter)Delegate.CreateDelegate (typeof (AddEventAdapter), addHandlerDelegate, adapterFrame, true);