Merge pull request #2721 from ludovic-henry/fix-mono_ms_ticks
[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                 public override Module Module {
55                         get {
56                                 return GetRuntimeModule ();
57                         }
58                 }
59
60                 internal RuntimeType GetDeclaringTypeInternal ()
61                 {
62                         return (RuntimeType) DeclaringType;
63                 }
64
65                 RuntimeType ReflectedTypeInternal {
66                         get {
67                                 return (RuntimeType) ReflectedType;
68                         }
69                 }
70
71                 internal RuntimeModule GetRuntimeModule ()
72                 {
73                         return GetDeclaringTypeInternal ().GetRuntimeModule ();
74                 }
75
76         #region ISerializable Implementation
77         public void GetObjectData(SerializationInfo info, StreamingContext context)
78         {
79             if (info == null)
80                 throw new ArgumentNullException("info");
81             Contract.EndContractBlock();
82             MemberInfoSerializationHolder.GetSerializationInfo(
83                 info,
84                 Name,
85                 ReflectedTypeInternal,
86                 ToString(),
87                 MemberTypes.Field);
88         }
89         #endregion
90         }
91
92         abstract class RtFieldInfo : RuntimeFieldInfo
93         {
94                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
95                 internal extern object UnsafeGetValue (object obj);
96
97         internal void CheckConsistency(Object target)
98         {
99             // only test instance fields
100             if ((Attributes & FieldAttributes.Static) != FieldAttributes.Static)
101             {
102                 if (!DeclaringType.IsInstanceOfType(target))
103                 {
104                     if (target == null)
105                     {
106 #if FEATURE_LEGACYNETCF
107                         if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8)
108                             throw new ArgumentNullException(Environment.GetResourceString("RFLCT.Targ_StatFldReqTarg"));
109                         else
110 #endif
111                         throw new TargetException(Environment.GetResourceString("RFLCT.Targ_StatFldReqTarg"));
112                     }
113                     else
114                     {
115                         throw new ArgumentException(
116                             String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Arg_FieldDeclTarget"),
117                                 Name, DeclaringType, target.GetType()));
118                     }
119                 }
120             }
121         }
122
123                 [DebuggerStepThroughAttribute]
124                 [Diagnostics.DebuggerHidden]
125                 internal void UnsafeSetValue (Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture)
126                 {
127                         bool domainInitialized = false;
128                         RuntimeFieldHandle.SetValue (this, obj, value, null, Attributes, null, ref domainInitialized);
129                 }
130
131         [DebuggerStepThroughAttribute]
132         [Diagnostics.DebuggerHidden]
133         public override void SetValueDirect(TypedReference obj, Object value)
134         {
135             if (obj.IsNull)
136                 throw new ArgumentException(Environment.GetResourceString("Arg_TypedReference_Null"));
137             Contract.EndContractBlock();
138
139             unsafe
140             {
141                 // Passing TypedReference by reference is easier to make correct in native code
142                 RuntimeFieldHandle.SetValueDirect(this, (RuntimeType)FieldType, &obj, value, (RuntimeType)DeclaringType);
143             }
144         }
145
146         [DebuggerStepThroughAttribute]
147         [Diagnostics.DebuggerHidden]
148         public override Object GetValueDirect(TypedReference obj)
149         {
150             if (obj.IsNull)
151                 throw new ArgumentException(Environment.GetResourceString("Arg_TypedReference_Null"));
152             Contract.EndContractBlock();
153
154             unsafe
155             {
156                 // Passing TypedReference by reference is easier to make correct in native code
157                 return RuntimeFieldHandle.GetValueDirect(this, (RuntimeType)FieldType, &obj, (RuntimeType)DeclaringType);
158             }
159         }
160         }
161
162         [Serializable]
163         [StructLayout (LayoutKind.Sequential)]
164         internal class MonoField : RtFieldInfo {
165                 internal IntPtr klass;
166                 internal RuntimeFieldHandle fhandle;
167                 string name;
168                 Type type;
169                 FieldAttributes attrs;
170                 
171                 public override FieldAttributes Attributes {
172                         get {
173                                 return attrs;
174                         }
175                 }
176                 public override RuntimeFieldHandle FieldHandle {
177                         get {
178                                 return fhandle;
179                         }
180                 }
181
182                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
183                 extern Type ResolveType ();
184
185                 public override Type FieldType { 
186                         get {
187                                 if (type == null)
188                                         type = ResolveType ();
189                                 return type;
190                         }
191                 }
192
193                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
194                 private extern Type GetParentType (bool declaring);
195
196                 public override Type ReflectedType {
197                         get {
198                                 return GetParentType (false);
199                         }
200                 }
201                 public override Type DeclaringType {
202                         get {
203                                 return GetParentType (true);
204                         }
205                 }
206                 public override string Name {
207                         get {
208                                 return name;
209                         }
210                 }
211
212                 public override bool IsDefined (Type attributeType, bool inherit) {
213                         return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
214                 }
215
216                 public override object[] GetCustomAttributes( bool inherit) {
217                         return MonoCustomAttrs.GetCustomAttributes (this, inherit);
218                 }
219                 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
220                         return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
221                 }
222
223                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
224                 internal override extern int GetFieldOffset ();
225
226                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
227                 private extern object GetValueInternal (object obj);
228
229                 public override object GetValue (object obj)
230                 {
231                         if (!IsStatic) {
232                                 if (obj == null)
233                                         throw new TargetException ("Non-static field requires a target");
234                                 if (!DeclaringType.IsAssignableFrom (obj.GetType ()))
235                                         throw new ArgumentException (string.Format (
236                                                 "Field {0} defined on type {1} is not a field on the target object which is of type {2}.",
237                                                 Name, DeclaringType, obj.GetType ()),
238                                                 "obj");
239                         }
240                         
241                         if (!IsLiteral)
242                                 CheckGeneric ();
243                         return GetValueInternal (obj);
244                 }
245
246                 public override string ToString () {
247                         return String.Format ("{0} {1}", FieldType, name);
248                 }
249
250                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
251                 private static extern void SetValueInternal (FieldInfo fi, object obj, object value);
252
253                 public override void SetValue (object obj, object val, BindingFlags invokeAttr, Binder binder, CultureInfo culture)
254                 {
255                         if (!IsStatic) {
256                                 if (obj == null)
257                                         throw new TargetException ("Non-static field requires a target");
258                                 if (!DeclaringType.IsAssignableFrom (obj.GetType ()))
259                                         throw new ArgumentException (string.Format (
260                                                 "Field {0} defined on type {1} is not a field on the target object which is of type {2}.",
261                                                 Name, DeclaringType, obj.GetType ()),
262                                                 "obj");
263                         }
264                         if (IsLiteral)
265                                 throw new FieldAccessException ("Cannot set a constant field");
266                         if (binder == null)
267                                 binder = Type.DefaultBinder;
268                         CheckGeneric ();
269                         if (val != null) {
270                                 RuntimeType fieldType = (RuntimeType) FieldType;
271                                 val = fieldType.CheckValue (val, binder, culture, invokeAttr);
272                         }
273                         SetValueInternal (this, obj, val);
274                 }
275                 
276                 internal MonoField Clone (string newName)
277                 {
278                         MonoField field = new MonoField ();
279                         field.name = newName;
280                         field.type = type;
281                         field.attrs = attrs;
282                         field.klass = klass;
283                         field.fhandle = fhandle;
284                         return field;
285                 }
286
287                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
288                 public override extern object GetRawConstantValue ();
289
290                 public override IList<CustomAttributeData> GetCustomAttributesData () {
291                         return CustomAttributeData.GetCustomAttributes (this);
292                 }
293
294                 void CheckGeneric () {
295                         if (DeclaringType.ContainsGenericParameters)
296                                 throw new InvalidOperationException ("Late bound operations cannot be performed on fields with types for which Type.ContainsGenericParameters is true.");
297             }
298
299 #if MOBILE
300                 static int get_core_clr_security_level ()
301                 {
302                         return 1;
303                 }
304 #else
305                 //seclevel { transparent = 0, safe-critical = 1, critical = 2}
306                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
307                 public extern int get_core_clr_security_level ();
308
309                 public override bool IsSecurityTransparent {
310                         get { return get_core_clr_security_level () == 0; }
311                 }
312
313                 public override bool IsSecurityCritical {
314                         get { return get_core_clr_security_level () > 0; }
315                 }
316
317                 public override bool IsSecuritySafeCritical {
318                         get { return get_core_clr_security_level () == 1; }
319                 }
320 #endif
321         }
322 }