[Mono-devel-list] [Patch] Reflection Only

Zoltan Varga vargaz at gmail.com
Wed Mar 9 11:42:20 EST 2005


                                       Hi,

  Here is a review of the custom attribute related changes:

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

Index: reflection.c
===================================================================
--- reflection.c	(revisión: 40470)
+++ reflection.c	(copia de trabajo)
@@ -6432,6 +6432,50 @@
 	return NULL;
 }
 
+static MonoObject*
+create_cattr_typed_arg (MonoType *t, void *val)
+{
+	static MonoClass *klass;
+	static MonoMethod *ctor;
+	MonoObject *retval;
+	void *params [2], *unboxed;
+
+	if (!klass) {
+		klass = mono_class_from_name (mono_defaults.corlib,
"System.Reflection", "CustomAttributeTypedArgument");
+		ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
+	}
+	

Split this into two pieces, ie. if (!klass) ... if (!ictor) ..., since doing
the two together is not thread safe.

+	params [0] = mono_type_get_object (mono_domain_get (), t);
+	params [1] = val;
+	retval = mono_object_new (mono_domain_get (), klass);
+	unboxed = mono_object_unbox (retval);
+	mono_runtime_invoke (ctor, unboxed, params, NULL);
+
+	return retval;
+}
+
+static MonoObject*
+create_cattr_named_arg (void *minfo, void *typedarg)
+{
+	static MonoClass *klass;
+	static MonoMethod *ctor;
+	MonoObject *retval;
+	void *unboxed, *params [2];
+
+	if (!klass) {
+		klass = mono_class_from_name (mono_defaults.corlib,
"System.Reflection", "CustomAttributeNamedArgument");
+		ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
+	}
+

Same as above.

+	params [0] = minfo;
+	params [1] = typedarg;
+	retval = mono_object_new (mono_domain_get (), klass);
+	unboxed = mono_object_unbox (retval);
+	mono_runtime_invoke (ctor, unboxed, params, NULL);
+
+	return retval;
+}
+
 static gboolean
 type_is_reference (MonoType *type)
 {
@@ -6595,3 +6639,18 @@
 	return attr;
 }
 
+static MonoObject*
+create_custom_attr_data (MonoImage *image, MonoMethod *method, const
char *data, guint32 len)
+{
+	MonoArray *typedargs, *namedargs;
+	MonoClass *klass, *attrklass;
+	MonoMethod *ctor;
+	MonoObject *attr;
+	const char *p = data;
+	const char *named;
+	guint32 i, j, num_named;
+	void *params [3], **ctorparams;
+
+	klass = mono_class_from_name (mono_defaults.corlib,
"System.Reflection", "CustomAttributeData");
+	ctor = mono_class_get_method_from_name (klass, ".ctor", 3);
+	

Cache klass and ctor in static variables as done in other parts of reflection.c.
Also cache the result of mono_domain_get () in a local variable.

+	if (len == 0) {
+		/* This is for Attributes with no parameters */
+		attr = mono_object_new (mono_domain_get (), klass);
+		params [0] = mono_method_get_object (mono_domain_get (), method, NULL);
+		params [1] = params [2] = NULL;
+		mono_runtime_invoke (method, attr, params, NULL);
+		return attr;
+	}
+
+	if (len < 2 || read16 (p) != 0x0001) /* Prolog */
+		return NULL;
+
+	ctorparams = g_new (void*, mono_method_signature (method)->param_count);
+	typedargs = mono_array_new (mono_domain_get (),
mono_get_object_class (), mono_method_signature
(method)->param_count);
+	
+	/* skip prolog */
+	p += 2;
+	for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
+		void *val;
+
+		ctorparams [i] = load_cattr_value (image, mono_method_signature
(method)->params [i], p, &p);
+		val = type_is_reference (mono_method_signature (method)->params [i]) ? 
+			ctorparams [i] : mono_value_box (mono_domain_get (),
mono_class_from_mono_type (mono_method_signature (method)->params
[i]), ctorparams [i]);
+		mono_array_set (typedargs, void*, i, create_cattr_typed_arg
(mono_method_signature (method)->params [i], val));
+	}
+

mono_array_set () is a macro, so the call to create_cattr_typed_arg should not
be done as an argument of it.

+	named = p;
+	free_param_data (method->signature, ctorparams);
+	g_free (ctorparams);
+	num_named = read16 (named);
+	namedargs = mono_array_new (mono_domain_get (),
mono_get_object_class (), num_named);
+	named += 2;
+	attrklass = method->klass;
+	for (j = 0; j < num_named; j++) {
+		gint name_len;
+		char *name, named_type, data_type;
+		named_type = *named++;
+		data_type = *named++; /* type of data */
+		if (data_type == 0x55) {
+			gint type_len;
+			char *type_name;
+			type_len = mono_metadata_decode_blob_size (named, &named);
+			type_name = g_malloc (type_len + 1);
+			memcpy (type_name, named, type_len);
+			type_name [type_len] = 0;
+			named += type_len;
+			/* FIXME: lookup the type and check type consistency */
+		} else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 ||
named_type == 0x53)) {
+			/* this seems to be the type of the element of the array */
+			/* g_print ("skipping 0x%02x after prop\n", *named); */
+			named++;
+		}
+		name_len = mono_metadata_decode_blob_size (named, &named);
+		name = g_malloc (name_len + 1);
+		memcpy (name, named, name_len);
+		name [name_len] = 0;
+		named += name_len;
+		if (named_type == 0x53) {
+			MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
+			void *obj, *minfo, *typedarg, *val = load_cattr_value (image,
field->type, named, &named);
+			
+			obj = type_is_reference (field->type) ? val : mono_value_box
(mono_domain_get (), mono_class_from_mono_type (field->type), val);
+			minfo = mono_field_get_object (mono_domain_get (), NULL, field);
+			typedarg = create_cattr_typed_arg (field->type, obj);
+			mono_array_set (namedargs, void*, j, create_cattr_named_arg
(minfo, typedarg));

Same as above.

+			if (!type_is_reference (field->type))
+				g_free (val);
+		} else if (named_type == 0x54) {
+			MonoType *prop_type;
+			void *val, *obj, *minfo, *typedarg;
+			MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
+
+			prop_type = prop->get? mono_method_signature (prop->get)->ret :
+			     mono_method_signature (prop->set)->params
[mono_method_signature (prop->set)->param_count - 1];
+			val = load_cattr_value (image, prop_type, named, &named);
+			obj = type_is_reference (prop_type) ? val : mono_value_box
(mono_domain_get (), mono_class_from_mono_type (prop_type), val);
+			minfo =  mono_property_get_object (mono_domain_get (), NULL, prop);
+			typedarg = create_cattr_typed_arg (prop_type, obj);
+			mono_array_set (namedargs, void*, j, create_cattr_named_arg
(minfo, typedarg));

Same as above.

+			if (!type_is_reference (prop_type))
+				g_free (val);
+		}
+		g_free (name);
+	}
+	attr = mono_object_new (mono_domain_get (), klass);
+	params [0] = mono_method_get_object (mono_domain_get (), method, NULL);
+	params [1] = typedargs;
+	params [2] = namedargs;
+	mono_runtime_invoke (ctor, attr, params, NULL);
+	return attr;
+}
+
 MonoArray*
 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
 {
@@ -6612,6 +6763,23 @@
 	return result;
 }
 
+MonoArray*
+mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
+{
+	MonoArray *result;
+	MonoClass *klass;
+	MonoObject *attr;
+	int i;
+
+	klass = mono_class_from_name (mono_defaults.corlib,
"System.Reflection", "CustomAttributeData");

Cache klass here.

+	result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
+	for (i = 0; i < cinfo->num_attrs; ++i) {
+		attr = create_custom_attr_data (cinfo->image, cinfo->attrs
[i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
+		mono_array_set (result, gpointer, i, attr);
+	}
+	return result;
+}
+
 MonoCustomAttrInfo*
 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
 {
@@ -6912,6 +7080,34 @@
 	return result;
 }
 
+/*
+ * mono_reflection_get_custom_attrs_data:
+ * @obj: a reflection obj handle
+ *
+ * Returns an array of System.Reflection.CustomAttributeData,
+ * which include information about attributes reflected on
+ * types loaded using the Reflection Only methods
+ */
+MonoArray*
+mono_reflection_get_custom_attrs_data (MonoObject *obj)
+{
+	MonoArray *result;
+	MonoCustomAttrInfo *cinfo;
+
+	cinfo = mono_reflection_get_custom_attrs_info (obj);
+	if (cinfo) {
+		result = mono_custom_attrs_data_construct (cinfo);
+		if (!cinfo->cached)
+			mono_custom_attrs_free (cinfo);
+	} else {
+		MonoClass *klass;
+		klass = mono_class_from_name (mono_defaults.corlib,
"System.Reflection", "CustomAttributeData");
+		result = mono_array_new (mono_domain_get (), klass, 0);
+	}
+

Cache klass here.

+	return result;
+}
+
 static MonoMethodSignature*
 parameters_to_signature (MonoArray *parameters) {
 	MonoMethodSignature *sig;

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

One thing which is missing is nunit tests for the 
GetCustomAttributeData () methods.

                                 Zoltan

On Wed, 16 Feb 2005 06:52:04 -0600, Carlos Alberto Cortez
<calberto.cortez at gmail.com> wrote:
> Hi,
> 
> This is the latest patch for implementing the support of ReflectionOnly
> methods that are part of the .Net Whidbey, with the last changes
> suggested by Paolo. I have also change the names from *_refonly to
> *_fullname, by a suggestion of Raja, and which I found much better.
> 
> It also adds support for retrieving CustomAttributeData, which is
> basically the attribute data itself.
> 
> Maybe could we commit this?
> 
> Carlos.
> 
> 
>



More information about the Mono-devel-list mailing list