[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