From 4b4aad7217d3292650e77eec2cf4c198ea9c3b4b Mon Sep 17 00:00:00 2001 From: Jiyoung Yun Date: Wed, 23 Nov 2016 19:09:09 +0900 Subject: Imported Upstream version 1.1.0 --- src/mscorlib/src/System/TypedReference.cs | 133 ++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 src/mscorlib/src/System/TypedReference.cs (limited to 'src/mscorlib/src/System/TypedReference.cs') diff --git a/src/mscorlib/src/System/TypedReference.cs b/src/mscorlib/src/System/TypedReference.cs new file mode 100644 index 0000000000..7c68c4164f --- /dev/null +++ b/src/mscorlib/src/System/TypedReference.cs @@ -0,0 +1,133 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System { + + // TypedReference is basically only ever seen on the call stack, and in param arrays. + // These are blob that must be dealt with by the compiler. + using System; + using System.Reflection; + using System.Runtime.CompilerServices; + using CultureInfo = System.Globalization.CultureInfo; + using FieldInfo = System.Reflection.FieldInfo; + using System.Security.Permissions; + using System.Runtime.Versioning; + using System.Diagnostics.Contracts; + + [CLSCompliant(false)] + [System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.Versioning.NonVersionable] // This only applies to field layout + public struct TypedReference + { + private IntPtr Value; + private IntPtr Type; + + [System.Security.SecurityCritical] // auto-generated_required + [CLSCompliant(false)] + public static TypedReference MakeTypedReference(Object target, FieldInfo[] flds) { + if (target == null) + throw new ArgumentNullException("target"); + if (flds == null) + throw new ArgumentNullException("flds"); + Contract.EndContractBlock(); + if (flds.Length == 0) + throw new ArgumentException(Environment.GetResourceString("Arg_ArrayZeroError")); + + IntPtr[] fields = new IntPtr[flds.Length]; + // For proper handling of Nullable don't change GetType() to something like 'IsAssignableFrom' + // Currently we can't make a TypedReference to fields of Nullable, which is fine. + RuntimeType targetType = (RuntimeType)target.GetType(); + for (int i = 0; i < flds.Length; i++) + { + RuntimeFieldInfo field = flds[i] as RuntimeFieldInfo; + if (field == null) + throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeFieldInfo")); + + if (field.IsInitOnly || field.IsStatic) + throw new ArgumentException(Environment.GetResourceString("Argument_TypedReferenceInvalidField")); + + if (targetType != field.GetDeclaringTypeInternal() && !targetType.IsSubclassOf(field.GetDeclaringTypeInternal())) + throw new MissingMemberException(Environment.GetResourceString("MissingMemberTypeRef")); + + RuntimeType fieldType = (RuntimeType)field.FieldType; + if (fieldType.IsPrimitive) + throw new ArgumentException(Environment.GetResourceString("Arg_TypeRefPrimitve")); + + if (i < (flds.Length - 1) && !fieldType.IsValueType) + throw new MissingMemberException(Environment.GetResourceString("MissingMemberNestErr")); + + fields[i] = field.FieldHandle.Value; + targetType = fieldType; + } + + TypedReference result = new TypedReference (); + + // reference to TypedReference is banned, so have to pass result as pointer + unsafe + { + InternalMakeTypedReference(&result, target, fields, targetType); + } + return result; + } + + [System.Security.SecurityCritical] // auto-generated + [MethodImplAttribute(MethodImplOptions.InternalCall)] + // reference to TypedReference is banned, so have to pass result as pointer + private unsafe static extern void InternalMakeTypedReference(void* result, Object target, IntPtr[] flds, RuntimeType lastFieldType); + + public override int GetHashCode() + { + if (Type == IntPtr.Zero) + return 0; + else + return __reftype(this).GetHashCode(); + } + + public override bool Equals(Object o) + { + throw new NotSupportedException(Environment.GetResourceString("NotSupported_NYI")); + } + + [System.Security.SecuritySafeCritical] // auto-generated + public unsafe static Object ToObject(TypedReference value) + { + return InternalToObject(&value); + } + + [System.Security.SecurityCritical] // auto-generated + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal unsafe extern static Object InternalToObject(void * value); + + internal bool IsNull + { + get + { + return Value.IsNull() && Type.IsNull(); + } + } + + public static Type GetTargetType (TypedReference value) + { + return __reftype(value); + } + + public static RuntimeTypeHandle TargetTypeToken (TypedReference value) + { + return __reftype(value).TypeHandle; + } + + // This may cause the type to be changed. + [System.Security.SecuritySafeCritical] // auto-generated + [CLSCompliant(false)] + public unsafe static void SetTypedReference(TypedReference target, Object value) + { + InternalSetTypedReference(&target, value); + } + + [System.Security.SecurityCritical] // auto-generated + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal unsafe extern static void InternalSetTypedReference(void * target, Object value); + } + +} -- cgit v1.2.3