Merge pull request #1634 from StephenMcConnel/bug-28025
[mono.git] / mcs / class / corlib / System.Reflection / MonoField.cs
1
2 //
3 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining
6 // a copy of this software and associated documentation files (the
7 // "Software"), to deal in the Software without restriction, including
8 // without limitation the rights to use, copy, modify, merge, publish,
9 // distribute, sublicense, and/or sell copies of the Software, and to
10 // permit persons to whom the Software is furnished to do so, subject to
11 // the following conditions:
12 // 
13 // The above copyright notice and this permission notice shall be
14 // included in all copies or substantial portions of the Software.
15 // 
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 //
24
25 //
26 // System.Reflection/MonoField.cs
27 // The class used to represent Fields from the mono runtime.
28 //
29 // Author:
30 //   Paolo Molaro (lupus@ximian.com)
31 //
32 // (C) 2001 Ximian, Inc.  http://www.ximian.com
33 //
34
35 using System;
36 using System.Collections.Generic;
37 using System.Globalization;
38 using System.Runtime.CompilerServices;
39 using System.Runtime.InteropServices;
40 using System.Runtime.Serialization;
41 using System.Diagnostics;
42 using System.Diagnostics.Contracts;
43
44 namespace System.Reflection {
45
46         abstract class RuntimeFieldInfo : FieldInfo, ISerializable
47         {
48                 internal BindingFlags BindingFlags {
49                         get {
50                                 return 0;
51                         }
52                 }
53
54                 internal RuntimeType GetDeclaringTypeInternal ()
55                 {
56                         return (RuntimeType) DeclaringType;
57                 }
58
59                 RuntimeType ReflectedTypeInternal {
60                         get {
61                                 return (RuntimeType) ReflectedType;
62                         }
63                 }
64
65         #region ISerializable Implementation
66         public void GetObjectData(SerializationInfo info, StreamingContext context)
67         {
68             if (info == null)
69                 throw new ArgumentNullException("info");
70             Contract.EndContractBlock();
71             MemberInfoSerializationHolder.GetSerializationInfo(
72                 info,
73                 Name,
74                 ReflectedTypeInternal,
75                 ToString(),
76                 MemberTypes.Field);
77         }
78         #endregion
79         }
80
81         abstract class RtFieldInfo : RuntimeFieldInfo
82         {
83                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
84                 internal extern object UnsafeGetValue (object obj);
85
86         internal void CheckConsistency(Object target)
87         {
88             // only test instance fields
89             if ((Attributes & FieldAttributes.Static) != FieldAttributes.Static)
90             {
91                 if (!DeclaringType.IsInstanceOfType(target))
92                 {
93                     if (target == null)
94                     {
95 #if FEATURE_LEGACYNETCF
96                         if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8)
97                             throw new ArgumentNullException(Environment.GetResourceString("RFLCT.Targ_StatFldReqTarg"));
98                         else
99 #endif
100                         throw new TargetException(Environment.GetResourceString("RFLCT.Targ_StatFldReqTarg"));
101                     }
102                     else
103                     {
104                         throw new ArgumentException(
105                             String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Arg_FieldDeclTarget"),
106                                 Name, DeclaringType, target.GetType()));
107                     }
108                 }
109             }
110         }
111
112                 [DebuggerStepThroughAttribute]
113                 [Diagnostics.DebuggerHidden]
114                 internal void UnsafeSetValue (Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture)
115                 {
116                         bool domainInitialized = false;
117                         RuntimeFieldHandle.SetValue (this, obj, value, null, Attributes, null, ref domainInitialized);
118                 }
119
120         [DebuggerStepThroughAttribute]
121         [Diagnostics.DebuggerHidden]
122         public override void SetValueDirect(TypedReference obj, Object value)
123         {
124             if (obj.IsNull)
125                 throw new ArgumentException(Environment.GetResourceString("Arg_TypedReference_Null"));
126             Contract.EndContractBlock();
127
128             unsafe
129             {
130                 // Passing TypedReference by reference is easier to make correct in native code
131                 RuntimeFieldHandle.SetValueDirect(this, (RuntimeType)FieldType, &obj, value, (RuntimeType)DeclaringType);
132             }
133         }
134
135         [DebuggerStepThroughAttribute]
136         [Diagnostics.DebuggerHidden]
137         public override Object GetValueDirect(TypedReference obj)
138         {
139             if (obj.IsNull)
140                 throw new ArgumentException(Environment.GetResourceString("Arg_TypedReference_Null"));
141             Contract.EndContractBlock();
142
143             unsafe
144             {
145                 // Passing TypedReference by reference is easier to make correct in native code
146                 return RuntimeFieldHandle.GetValueDirect(this, (RuntimeType)FieldType, &obj, (RuntimeType)DeclaringType);
147             }
148         }
149         }
150
151         [Serializable]
152         [StructLayout (LayoutKind.Sequential)]
153         internal class MonoField : RtFieldInfo {
154                 internal IntPtr klass;
155                 internal RuntimeFieldHandle fhandle;
156                 string name;
157                 Type type;
158                 FieldAttributes attrs;
159                 
160                 public override FieldAttributes Attributes {
161                         get {
162                                 return attrs;
163                         }
164                 }
165                 public override RuntimeFieldHandle FieldHandle {
166                         get {
167                                 return fhandle;
168                         }
169                 }
170
171                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
172                 extern Type ResolveType ();
173
174                 public override Type FieldType { 
175                         get {
176                                 if (type == null)
177                                         type = ResolveType ();
178                                 return type;
179                         }
180                 }
181
182                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
183                 private extern Type GetParentType (bool declaring);
184
185                 public override Type ReflectedType {
186                         get {
187                                 return GetParentType (false);
188                         }
189                 }
190                 public override Type DeclaringType {
191                         get {
192                                 return GetParentType (true);
193                         }
194                 }
195                 public override string Name {
196                         get {
197                                 return name;
198                         }
199                 }
200
201                 public override bool IsDefined (Type attributeType, bool inherit) {
202                         return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
203                 }
204
205                 public override object[] GetCustomAttributes( bool inherit) {
206                         return MonoCustomAttrs.GetCustomAttributes (this, inherit);
207                 }
208                 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
209                         return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
210                 }
211
212                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
213                 internal override extern int GetFieldOffset ();
214
215                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
216                 private extern object GetValueInternal (object obj);
217
218                 public override object GetValue (object obj)
219                 {
220                         if (!IsStatic) {
221                                 if (obj == null)
222                                         throw new TargetException ("Non-static field requires a target");
223                                 if (!DeclaringType.IsAssignableFrom (obj.GetType ()))
224                                         throw new ArgumentException (string.Format (
225                                                 "Field {0} defined on type {1} is not a field on the target object which is of type {2}.",
226                                                 Name, DeclaringType, obj.GetType ()),
227                                                 "obj");
228                         }
229                         
230                         if (!IsLiteral)
231                                 CheckGeneric ();
232                         return GetValueInternal (obj);
233                 }
234
235                 public override string ToString () {
236                         return String.Format ("{0} {1}", FieldType, name);
237                 }
238
239                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
240                 private static extern void SetValueInternal (FieldInfo fi, object obj, object value);
241
242                 public override void SetValue (object obj, object val, BindingFlags invokeAttr, Binder binder, CultureInfo culture)
243                 {
244                         if (!IsStatic) {
245                                 if (obj == null)
246                                         throw new TargetException ("Non-static field requires a target");
247                                 if (!DeclaringType.IsAssignableFrom (obj.GetType ()))
248                                         throw new ArgumentException (string.Format (
249                                                 "Field {0} defined on type {1} is not a field on the target object which is of type {2}.",
250                                                 Name, DeclaringType, obj.GetType ()),
251                                                 "obj");
252                         }
253                         if (IsLiteral)
254                                 throw new FieldAccessException ("Cannot set a constant field");
255                         if (binder == null)
256                                 binder = Type.DefaultBinder;
257                         CheckGeneric ();
258                         if (val != null) {
259                                 RuntimeType fieldType = (RuntimeType) FieldType;
260                                 val = fieldType.CheckValue (val, binder, culture, invokeAttr);
261                         }
262                         SetValueInternal (this, obj, val);
263                 }
264                 
265                 internal MonoField Clone (string newName)
266                 {
267                         MonoField field = new MonoField ();
268                         field.name = newName;
269                         field.type = type;
270                         field.attrs = attrs;
271                         field.klass = klass;
272                         field.fhandle = fhandle;
273                         return field;
274                 }
275
276                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
277                 public override extern object GetRawConstantValue ();
278
279                 public override IList<CustomAttributeData> GetCustomAttributesData () {
280                         return CustomAttributeData.GetCustomAttributes (this);
281                 }
282
283                 void CheckGeneric () {
284                         if (DeclaringType.ContainsGenericParameters)
285                                 throw new InvalidOperationException ("Late bound operations cannot be performed on fields with types for which Type.ContainsGenericParameters is true.");
286             }
287
288                 //seclevel { transparent = 0, safe-critical = 1, critical = 2}
289                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
290                 public extern int get_core_clr_security_level ();
291
292                 public override bool IsSecurityTransparent {
293                         get { return get_core_clr_security_level () == 0; }
294                 }
295
296                 public override bool IsSecurityCritical {
297                         get { return get_core_clr_security_level () > 0; }
298                 }
299
300                 public override bool IsSecuritySafeCritical {
301                         get { return get_core_clr_security_level () == 1; }
302                 }
303         }
304 }