3 // Copyright (c) Microsoft Corporation. All rights reserved.
8 // TypedReference is basically only ever seen on the call stack, and in param arrays.
9 // These are blob that must be dealt with by the compiler.
11 using System.Reflection;
12 using System.Runtime.CompilerServices;
13 using CultureInfo = System.Globalization.CultureInfo;
14 using FieldInfo = System.Reflection.FieldInfo;
15 using System.Security.Permissions;
16 using System.Runtime.Versioning;
17 using System.Diagnostics.Contracts;
20 [System.Runtime.InteropServices.ComVisible(true)]
21 [System.Runtime.Versioning.NonVersionable] // This only applies to field layout
22 public struct TypedReference
25 #pragma warning disable 169
26 RuntimeTypeHandle type;
27 #pragma warning restore
32 [System.Security.SecurityCritical] // auto-generated_required
34 public static TypedReference MakeTypedReference(Object target, FieldInfo[] flds) {
36 throw new ArgumentNullException("target");
38 throw new ArgumentNullException("flds");
39 Contract.EndContractBlock();
41 throw new ArgumentException(Environment.GetResourceString("Arg_ArrayZeroError"));
43 IntPtr[] fields = new IntPtr[flds.Length];
44 // For proper handling of Nullable<T> don't change GetType() to something like 'IsAssignableFrom'
45 // Currently we can't make a TypedReference to fields of Nullable<T>, which is fine.
46 RuntimeType targetType = (RuntimeType)target.GetType();
47 for (int i = 0; i < flds.Length; i++)
49 RuntimeFieldInfo field = flds[i] as RuntimeFieldInfo;
51 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeFieldInfo"));
53 if (field.IsInitOnly || field.IsStatic)
54 throw new ArgumentException(Environment.GetResourceString("Argument_TypedReferenceInvalidField"));
56 if (targetType != field.GetDeclaringTypeInternal() && !targetType.IsSubclassOf(field.GetDeclaringTypeInternal()))
57 throw new MissingMemberException(Environment.GetResourceString("MissingMemberTypeRef"));
59 RuntimeType fieldType = (RuntimeType)field.FieldType;
60 if (fieldType.IsPrimitive)
61 throw new ArgumentException(Environment.GetResourceString("Arg_TypeRefPrimitve"));
63 if (i < (flds.Length - 1) && !fieldType.IsValueType)
64 throw new MissingMemberException(Environment.GetResourceString("MissingMemberNestErr"));
66 fields[i] = field.FieldHandle.Value;
67 targetType = fieldType;
71 return MakeTypedReferenceInternal (target, flds);
73 TypedReference result = new TypedReference ();
75 // reference to TypedReference is banned, so have to pass result as pointer
78 InternalMakeTypedReference(&result, target, fields, targetType);
84 [System.Security.SecurityCritical] // auto-generated
85 [ResourceExposure(ResourceScope.None)]
86 [MethodImplAttribute(MethodImplOptions.InternalCall)]
88 extern static TypedReference MakeTypedReferenceInternal (object target, FieldInfo[] fields);
90 // reference to TypedReference is banned, so have to pass result as pointer
91 private unsafe static extern void InternalMakeTypedReference(void* result, Object target, IntPtr[] flds, RuntimeType lastFieldType);
93 public override int GetHashCode()
95 if (Type == IntPtr.Zero)
98 return __reftype(this).GetHashCode();
101 public override bool Equals(Object o)
103 throw new NotSupportedException(Environment.GetResourceString("NotSupported_NYI"));
106 [System.Security.SecuritySafeCritical] // auto-generated
107 public unsafe static Object ToObject(TypedReference value)
109 return InternalToObject(&value);
112 [System.Security.SecurityCritical] // auto-generated
113 [ResourceExposure(ResourceScope.None)]
114 [MethodImplAttribute(MethodImplOptions.InternalCall)]
115 internal unsafe extern static Object InternalToObject(void * value);
121 return Value.IsNull() && Type.IsNull();
125 public static Type GetTargetType (TypedReference value)
127 return __reftype(value);
130 public static RuntimeTypeHandle TargetTypeToken (TypedReference value)
132 return __reftype(value).TypeHandle;
135 // This may cause the type to be changed.
136 [System.Security.SecuritySafeCritical] // auto-generated
137 [CLSCompliant(false)]
138 public unsafe static void SetTypedReference(TypedReference target, Object value)
141 throw new NotImplementedException ("SetTypedReference");
143 InternalSetTypedReference(&target, value);
147 [System.Security.SecurityCritical] // auto-generated
148 [ResourceExposure(ResourceScope.None)]
149 [MethodImplAttribute(MethodImplOptions.InternalCall)]
150 internal unsafe extern static void InternalSetTypedReference(void * target, Object value);