[reflection] Add System.Reflection.EventInfo.GetEventFromHandle methods
authorAleksey Kliger <aleksey@xamarin.com>
Thu, 14 Jul 2016 18:41:37 +0000 (14:41 -0400)
committerAleksey Kliger <aleksey@xamarin.com>
Thu, 14 Jul 2016 19:19:57 +0000 (15:19 -0400)
Add new Mono.RuntimeEventHandle struct wrapping a pointer to a native MonoEvent

Add new icall
ves_icall_System_Reflection_EventInfo_internal_from_handle_type that's
mostly a wrapper around mono_event_get_object_checked.

mcs/class/corlib/Mono/RuntimeHandles.cs
mcs/class/corlib/System.Reflection/EventInfo.cs
mono/metadata/icall-def.h
mono/metadata/icall.c

index e916332db325aa43d11951dc39d38fabbbe65dac..64bf12b3719b4a25764f2ef368fcd29fef32c04c 100644 (file)
@@ -142,6 +142,49 @@ namespace Mono {
                }
        }
 
+       internal struct RuntimeEventHandle {
+               IntPtr value;
+
+               internal RuntimeEventHandle (IntPtr v)
+               {
+                       value = v;
+               }
+
+               public IntPtr Value {
+                       get {
+                               return value;
+                       }
+               }
+
+               public override bool Equals (object obj)
+               {
+                       if (obj == null || GetType () != obj.GetType ())
+                               return false;
+
+                       return value == ((RuntimeEventHandle)obj).Value;
+               }
+
+               public bool Equals (RuntimeEventHandle handle)
+               {
+                       return value == handle.Value;
+               }
+
+               public override int GetHashCode ()
+               {
+                       return value.GetHashCode ();
+               }
+
+               public static bool operator == (RuntimeEventHandle left, RuntimeEventHandle right)
+               {
+                       return left.Equals (right);
+               }
+
+               public static bool operator != (RuntimeEventHandle left, RuntimeEventHandle right)
+               {
+                       return !left.Equals (right);
+               }
+       }
+
        internal struct RuntimeGPtrArrayHandle {
                unsafe RuntimeStructs.GPtrArray* value;
 
index 040fe38beaecdf099e2f28bdb8b572bdfcba458c..9668f1f56c2b85e6bd47899349e8a2b6323fdb79 100644 (file)
@@ -28,6 +28,7 @@
 //
 
 using System.Diagnostics;
+using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 
 namespace System.Reflection {
@@ -277,5 +278,25 @@ namespace System.Reflection {
                public virtual MethodInfo RemoveMethod {
                        get { return GetRemoveMethod (true); }
                }
+
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               private static extern EventInfo internal_from_handle_type (IntPtr event_handle, IntPtr type_handle);
+
+               internal static EventInfo GetEventFromHandle (Mono.RuntimeEventHandle handle)
+               {
+                       if (handle.Value == IntPtr.Zero)
+                               throw new ArgumentException ("The handle is invalid.");
+                       return internal_from_handle_type (handle.Value, IntPtr.Zero);
+               }
+
+               internal static EventInfo GetEventFromHandle (Mono.RuntimeEventHandle handle, RuntimeTypeHandle reflectedType)
+               {
+                       if (handle.Value == IntPtr.Zero)
+                               throw new ArgumentException ("The handle is invalid.");
+                       EventInfo ei = internal_from_handle_type (handle.Value, reflectedType.Value);
+                       if (ei == null)
+                               throw new ArgumentException ("The event handle and the type handle are incompatible.");
+                       return ei;
+               }
        }
 }
index f27705f32182c169244da0d3b2686a5dcdc3fff0..adf3d0eda969e2607c25a1ddf191df2ee6ec6314 100644 (file)
@@ -548,6 +548,9 @@ ICALL(TYPEB_5, "get_event_info", mono_reflection_event_builder_get_event_info)
 ICALL(TYPEB_6, "setup_generic_class", mono_reflection_setup_generic_class)
 ICALL(TYPEB_7, "setup_internal_class", mono_reflection_setup_internal_class)
 
+ICALL_TYPE(EVENTI, "System.Reflection.EventInfo", EVENTI_1)
+ICALL(EVENTI_1, "internal_from_handle_type", ves_icall_System_Reflection_EventInfo_internal_from_handle_type)
+
 ICALL_TYPE(FIELDI, "System.Reflection.FieldInfo", FILEDI_1)
 ICALL(FILEDI_1, "GetTypeModifiers", ves_icall_System_Reflection_FieldInfo_GetTypeModifiers)
 ICALL(FILEDI_2, "get_marshal_info", ves_icall_System_Reflection_FieldInfo_get_marshal_info)
index b48e23bcfe19edf2f745cfd776046a0faf314b48..4f3afb96a83b8ca10690a189bdf4584a2e9f7ee5 100644 (file)
@@ -1785,6 +1785,30 @@ ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField
        return result;
 }
 
+ICALL_EXPORT MonoReflectionEvent*
+ves_icall_System_Reflection_EventInfo_internal_from_handle_type (MonoEvent *handle, MonoType *type)
+{
+       MonoError error;
+       MonoClass *klass;
+
+       g_assert (handle);
+
+       if (!type) {
+               klass = handle->parent;
+       } else {
+               klass = mono_class_from_mono_type (type);
+
+               gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
+               if (!found)
+                       /* Managed code will throw an exception */
+                       return NULL;
+       }
+
+       MonoReflectionEvent *result = mono_event_get_object_checked (mono_domain_get (), klass, handle, &error);
+       mono_error_set_pending_exception (&error);
+       return result;
+}
+
 ICALL_EXPORT MonoArray*
 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
 {