Implementation of GetLoopbackInterfaceIndex on Windows
[mono.git] / mcs / class / referencesource / mscorlib / system / typedreference.cs
1 // ==++==
2 //
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 //
5 // ==--==
6 namespace System {
7
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.
10     using System;
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;
18
19     [CLSCompliant(false)] 
20     [System.Runtime.InteropServices.ComVisible(true)]
21     [System.Runtime.Versioning.NonVersionable] // This only applies to field layout
22     public struct TypedReference
23     {
24 #if MONO
25         RuntimeTypeHandle type;
26 #endif
27         private IntPtr Value;
28         private IntPtr Type;
29
30         [System.Security.SecurityCritical]  // auto-generated_required
31         [CLSCompliant(false)]
32         public static TypedReference MakeTypedReference(Object target, FieldInfo[] flds) {
33             if (target == null)
34                 throw new ArgumentNullException("target");
35             if (flds == null)
36                 throw new ArgumentNullException("flds");
37             Contract.EndContractBlock();
38             if (flds.Length == 0)
39                 throw new ArgumentException(Environment.GetResourceString("Arg_ArrayZeroError"));
40
41             IntPtr[] fields = new IntPtr[flds.Length];
42             // For proper handling of Nullable<T> don't change GetType() to something like 'IsAssignableFrom'
43             // Currently we can't make a TypedReference to fields of Nullable<T>, which is fine.  
44             RuntimeType targetType = (RuntimeType)target.GetType();
45             for (int i = 0; i < flds.Length; i++)
46             {
47                 RuntimeFieldInfo field = flds[i] as RuntimeFieldInfo;
48                 if (field == null)
49                     throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeFieldInfo"));
50
51                 if (field.IsInitOnly || field.IsStatic)
52                     throw new ArgumentException(Environment.GetResourceString("Argument_TypedReferenceInvalidField"));
53                 
54                 if (targetType != field.GetDeclaringTypeInternal() && !targetType.IsSubclassOf(field.GetDeclaringTypeInternal()))
55                     throw new MissingMemberException(Environment.GetResourceString("MissingMemberTypeRef"));
56
57                 RuntimeType fieldType = (RuntimeType)field.FieldType;
58                 if (fieldType.IsPrimitive)
59                     throw new ArgumentException(Environment.GetResourceString("Arg_TypeRefPrimitve"));
60                 
61                 if (i < (flds.Length - 1) && !fieldType.IsValueType)
62                     throw new MissingMemberException(Environment.GetResourceString("MissingMemberNestErr"));
63                 
64                 fields[i] = field.FieldHandle.Value;
65                 targetType = fieldType;
66             }
67
68 #if MONO
69             return MakeTypedReferenceInternal (target, flds);
70 #else
71             TypedReference result = new TypedReference ();
72
73             // reference to TypedReference is banned, so have to pass result as pointer
74             unsafe 
75             {
76                 InternalMakeTypedReference(&result, target, fields, targetType);
77             }
78             return result;
79 #endif
80         }
81
82         [System.Security.SecurityCritical]  // auto-generated
83         [ResourceExposure(ResourceScope.None)]
84         [MethodImplAttribute(MethodImplOptions.InternalCall)]
85 #if MONO
86         extern static TypedReference MakeTypedReferenceInternal (object target, FieldInfo[] fields);
87 #else
88         // reference to TypedReference is banned, so have to pass result as pointer
89         private unsafe static extern void InternalMakeTypedReference(void* result, Object target, IntPtr[] flds, RuntimeType lastFieldType);
90 #endif
91         public override int GetHashCode()
92         {
93             if (Type == IntPtr.Zero)
94                 return 0;
95             else
96                 return __reftype(this).GetHashCode();
97         }
98
99         public override bool Equals(Object o)
100         {
101             throw new NotSupportedException(Environment.GetResourceString("NotSupported_NYI"));
102         }
103
104         [System.Security.SecuritySafeCritical]  // auto-generated
105         public unsafe static Object ToObject(TypedReference value)
106         {
107             return InternalToObject(&value);
108         }
109
110         [System.Security.SecurityCritical]  // auto-generated
111         [ResourceExposure(ResourceScope.None)]
112         [MethodImplAttribute(MethodImplOptions.InternalCall)]
113         internal unsafe extern static Object InternalToObject(void * value);
114
115         internal bool IsNull 
116         { 
117             get
118             {
119                 return Value.IsNull() && Type.IsNull(); 
120             }
121         }
122
123         public static Type GetTargetType (TypedReference value)
124         {
125             return __reftype(value);
126         }
127
128         public static RuntimeTypeHandle TargetTypeToken (TypedReference value)
129         {
130             return __reftype(value).TypeHandle;
131         }
132
133         //  This may cause the type to be changed.
134         [System.Security.SecuritySafeCritical]  // auto-generated
135         [CLSCompliant(false)]
136         public unsafe static void SetTypedReference(TypedReference target, Object value)
137         {
138 #if MONO
139             throw new NotImplementedException ("SetTypedReference");
140 #else
141             InternalSetTypedReference(&target, value);
142 #endif
143         }
144 #if !MONO
145         [System.Security.SecurityCritical]  // auto-generated
146         [ResourceExposure(ResourceScope.None)]
147         [MethodImplAttribute(MethodImplOptions.InternalCall)]
148         internal unsafe extern static void InternalSetTypedReference(void * target, Object value);
149 #endif
150     }
151
152 }