if (mono_class_is_transparent_proxy (klass)) {
MonoTransparentProxyHandle proxy_obj = MONO_HANDLE_CAST (MonoTransparentProxy, obj);
MonoRemoteClass *remote_class = MONO_HANDLE_GETVAL (proxy_obj, remote_class);
- MonoType *proxy_type = &remote_class->proxy_class->byval_arg;
+ /* If it's a transparent proxy for an interface, return the
+ * interface type, not the unhelpful proxy_class class (which
+ * is just MarshalByRefObject). */
+ MonoType *proxy_type =
+ mono_remote_class_is_interface_proxy (remote_class) ?
+ &remote_class->interfaces[0]->byval_arg :
+ &remote_class->proxy_class->byval_arg;
return mono_type_get_object_handle (domain, proxy_type, error);
} else
#endif
MonoRemoteClass*
mono_remote_class (MonoDomain *domain, MonoStringHandle class_name, MonoClass *proxy_class, MonoError *error);
+gboolean
+mono_remote_class_is_interface_proxy (MonoRemoteClass *remote_class);
+
MonoObject *
mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg, MonoObject **exc, MonoArray **out_args, MonoError *error);
}
#ifndef DISABLE_REMOTING
+/**
+ * mono_remote_class_is_interface_proxy:
+ * \param remote_class
+ *
+ * Returns TRUE if the given remote class is a proxying an interface (as
+ * opposed to a class deriving from MarshalByRefObject).
+ */
+gboolean
+mono_remote_class_is_interface_proxy (MonoRemoteClass *remote_class)
+{
+ /* This if condition is taking advantage of how mono_remote_class ()
+ * works: if that code changes, this needs to change too. */
+ return (remote_class->interface_count >= 1 &&
+ remote_class->proxy_class == mono_defaults.marshalbyrefobject_class);
+}
+
/**
* mono_class_proxy_vtable:
* \param domain the application domain
/* we need to keep the GC descriptor for a transparent proxy or we confuse the precise GC */
pvt->gc_descr = mono_defaults.transparent_proxy_class->gc_descr;
+ if (mono_remote_class_is_interface_proxy (remote_class)) {
+ /* If it's a transparent proxy for an interface, set the
+ * MonoVTable:type to the interface type, not the placeholder
+ * MarshalByRefObject class. This is used when mini JITs calls
+ * to Object.GetType ()
+ */
+ MonoType *itf_proxy_type = &remote_class->interfaces[0]->byval_arg;
+ pvt->type = mono_type_get_object_checked (domain, itf_proxy_type, error);
+ if (!is_ok (error))
+ goto failure;
+ }
+
/* initialize vtable */
mono_class_setup_vtable (klass);
for (i = 0; i < klass->vtable_size; ++i) {
key = mp_key;
if (mono_class_is_interface (proxy_class)) {
+ /* If we need to proxy an interface, we use this stylized
+ * representation (interface_count >= 1, proxy_class is
+ * MarshalByRefObject). The code in
+ * mono_remote_class_is_interface_proxy () depends on being
+ * able to detect that we're doing this, so if this
+ * representation changes, change GetType, too. */
rc = (MonoRemoteClass *)mono_domain_alloc (domain, MONO_SIZEOF_REMOTE_CLASS + sizeof(MonoClass*));
rc->interface_count = 1;
rc->interfaces [0] = proxy_class;