if (flds.Length == 0) {
throw new ArgumentException (Locale.GetText ("flds has no elements"));
}
- throw new NotImplementedException ();
+
+ return MakeTypedReferenceInternal (target, flds);
}
/* how can we set something in value if it's passed by value? */
[MethodImpl (MethodImplOptions.InternalCall)]
public extern static object ToObject (TypedReference value);
+
+ [MethodImpl (MethodImplOptions.InternalCall)]
+ extern static TypedReference MakeTypedReferenceInternal (object target, FieldInfo[] fields);
}
}
//
using System;
+using System.Reflection;
using NUnit.Framework;
namespace MonoTests.System
TypedReference ti = __makeref(fields);
Assert.AreEqual (typeof (TestFields), TypedReference.GetTargetType (ti));
}
+
+ struct AStruct {
+ public int b;
+ }
+
+ class CClass {
+ public AStruct a;
+ }
+
+ [Test]
+ public void MakeTypedReference ()
+ {
+ var o = new CClass () { a = new AStruct () { b = 5 }};
+ TypedReference r = TypedReference.MakeTypedReference (o, new FieldInfo[] { typeof (CClass).GetField ("a"), typeof (AStruct).GetField ("b") });
+ Assert.AreEqual (5, TypedReference.ToObject (r));
+ }
}
}
ICALL(TYPE_2, "internal_from_name", ves_icall_type_from_name)
ICALL_TYPE(TYPEDR, "System.TypedReference", TYPEDR_1)
-ICALL(TYPEDR_1, "ToObject", mono_TypedReference_ToObject)
-ICALL(TYPEDR_2, "ToObjectInternal", mono_TypedReference_ToObjectInternal)
+ICALL(TYPEDR_1, "MakeTypedReferenceInternal", mono_TypedReference_MakeTypedReferenceInternal)
+ICALL(TYPEDR_2, "ToObject", mono_TypedReference_ToObject)
+ICALL(TYPEDR_3, "ToObjectInternal", mono_TypedReference_ToObjectInternal)
ICALL_TYPE(VALUET, "System.ValueType", VALUET_1)
ICALL(VALUET_1, "InternalEquals", ves_icall_System_ValueType_Equals)
return mono_value_box (mono_domain_get (), klass, value);
}
+ICALL_EXPORT MonoTypedRef
+mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
+{
+ MonoTypedRef res;
+ MonoReflectionField *f;
+ MonoClass *klass;
+ MonoType *ftype;
+ guint8 *p;
+ int i;
+
+ memset (&res, 0, sizeof (res));
+
+ g_assert (fields);
+ g_assert (mono_array_length (fields) > 0);
+
+ klass = target->vtable->klass;
+
+ for (i = 0; i < mono_array_length (fields); ++i) {
+ f = mono_array_get (fields, MonoReflectionField*, i);
+ if (f == NULL) {
+ mono_set_pending_exception (mono_get_exception_argument_null ("field"));
+ return res;
+ }
+ if (f->field->parent != klass) {
+ mono_set_pending_exception (mono_get_exception_argument ("field", ""));
+ return res;
+ }
+ if (i == 0)
+ p = (guint8*)target + f->field->offset;
+ else
+ p += f->field->offset - sizeof (MonoObject);
+ klass = mono_class_from_mono_type (f->field->type);
+ ftype = f->field->type;
+ }
+
+ res.type = ftype;
+ res.klass = mono_class_from_mono_type (ftype);
+ res.value = p;
+
+ return res;
+}
+
static void
prelink_method (MonoMethod *method)
{