9f7f9494b4ad8fb6561d9a21185f3e606ecb9eb1
[mono.git] / mcs / class / referencesource / mscorlib / system / reflection / fieldinfo.cs
1 // ==++==
2 // 
3 //   Copyright(c) Microsoft Corporation.  All rights reserved.
4 // 
5 // ==--==
6 // <OWNER>Microsoft</OWNER>
7 // 
8
9 namespace System.Reflection
10 {
11     using System;
12     using System.Collections.Generic;
13     using System.Diagnostics;
14     using System.Diagnostics.Contracts;
15     using System.Globalization;
16     using System.Runtime;
17     using System.Runtime.CompilerServices;
18     using System.Runtime.ConstrainedExecution;
19     using System.Runtime.InteropServices;
20 #if FEATURE_REMOTING
21     using System.Runtime.Remoting.Metadata;
22 #endif //FEATURE_REMOTING
23     using System.Runtime.Serialization;
24     using System.Security.Permissions;
25     using System.Threading;
26     using RuntimeTypeCache = System.RuntimeType.RuntimeTypeCache;
27
28     [Serializable]
29     [ClassInterface(ClassInterfaceType.None)]
30     [ComDefaultInterface(typeof(_FieldInfo))]
31 #pragma warning disable 618
32     [PermissionSetAttribute(SecurityAction.InheritanceDemand, Name = "FullTrust")]
33 #pragma warning restore 618
34     [System.Runtime.InteropServices.ComVisible(true)]
35     public abstract class FieldInfo : MemberInfo, _FieldInfo
36     {
37         #region Static Members
38         public static FieldInfo GetFieldFromHandle(RuntimeFieldHandle handle)
39         {
40             if (handle.IsNullHandle())
41                 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidHandle"));
42                 
43             FieldInfo f = RuntimeType.GetFieldInfo(handle.GetRuntimeFieldInfo());
44                        
45             Type declaringType = f.DeclaringType;
46             if (declaringType != null && declaringType.IsGenericType)
47                 throw new ArgumentException(String.Format(
48                     CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_FieldDeclaringTypeGeneric"), 
49                     f.Name, declaringType.GetGenericTypeDefinition()));
50
51             return f;            
52         }           
53         
54         [System.Runtime.InteropServices.ComVisible(false)]
55         public static FieldInfo GetFieldFromHandle(RuntimeFieldHandle handle, RuntimeTypeHandle declaringType)
56         {
57             if (handle.IsNullHandle())
58                 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidHandle"));
59
60             return RuntimeType.GetFieldInfo(declaringType.GetRuntimeType(), handle.GetRuntimeFieldInfo());
61         }           
62         #endregion
63
64         #region Constructor
65         protected FieldInfo() { }       
66         #endregion
67
68 #if !FEATURE_CORECLR
69         public static bool operator ==(FieldInfo left, FieldInfo right)
70         {
71             if (ReferenceEquals(left, right))
72                 return true;
73
74             if ((object)left == null || (object)right == null ||
75                 left is RuntimeFieldInfo || right is RuntimeFieldInfo)
76             {
77                 return false;
78             }
79             return left.Equals(right);
80         }
81
82         public static bool operator !=(FieldInfo left, FieldInfo right)
83         {
84             return !(left == right);
85         }
86 #endif // !FEATURE_CORECLR
87
88         public override bool Equals(object obj)
89         {
90             return base.Equals(obj);
91         }
92
93         public override int GetHashCode()
94         {
95             return base.GetHashCode();
96         }
97
98         #region MemberInfo Overrides
99         public override MemberTypes MemberType { get { return System.Reflection.MemberTypes.Field; } }
100         #endregion
101
102         #region Public Abstract\Virtual Members
103         
104         public virtual Type[] GetRequiredCustomModifiers()
105         {
106             throw new NotImplementedException();
107         }
108
109         public virtual Type[] GetOptionalCustomModifiers()
110         {
111             throw new NotImplementedException();
112         }
113
114         [CLSCompliant(false)]
115         public virtual void SetValueDirect(TypedReference obj, Object value)
116         {
117             throw new NotSupportedException(Environment.GetResourceString("NotSupported_AbstractNonCLS"));
118         }
119
120         [CLSCompliant(false)]
121         public virtual Object GetValueDirect(TypedReference obj)
122         {
123             throw new NotSupportedException(Environment.GetResourceString("NotSupported_AbstractNonCLS"));
124         }    
125
126         public abstract RuntimeFieldHandle FieldHandle { get; }
127
128         public abstract Type FieldType { get; }    
129      
130         public abstract Object GetValue(Object obj);
131
132         public virtual Object GetRawConstantValue() { throw new NotSupportedException(Environment.GetResourceString("NotSupported_AbstractNonCLS")); }
133
134         public abstract void SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture);
135
136         public abstract FieldAttributes Attributes { get; }
137         #endregion
138
139         #region Public Members
140         [DebuggerStepThroughAttribute]
141         [Diagnostics.DebuggerHidden]
142         public void SetValue(Object obj, Object value)
143         {
144             // Theoretically we should set up a LookForMyCaller stack mark here and pass that along.
145             // But to maintain backward compatibility we can't switch to calling an 
146             // internal overload that takes a stack mark.
147             // Fortunately the stack walker skips all the reflection invocation frames including this one.
148             // So this method will never be returned by the stack walker as the caller.
149             // See SystemDomain::CallersMethodCallbackWithStackMark in AppDomain.cpp.
150             SetValue(obj, value, BindingFlags.Default, Type.DefaultBinder, null);
151         }
152
153         public bool IsPublic { get { return(Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Public; } }
154
155         public bool IsPrivate { get { return(Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Private; } }
156
157         public bool IsFamily { get { return(Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Family; } }
158
159         public bool IsAssembly { get { return(Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Assembly; } }
160
161         public bool IsFamilyAndAssembly { get { return(Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.FamANDAssem; } }
162
163         public bool IsFamilyOrAssembly { get { return(Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.FamORAssem; } }
164
165         public bool IsStatic { get { return(Attributes & FieldAttributes.Static) != 0; } }
166
167         public bool IsInitOnly { get { return(Attributes & FieldAttributes.InitOnly) != 0; } }
168
169         public bool IsLiteral { get { return(Attributes & FieldAttributes.Literal) != 0; } }
170
171         public bool IsNotSerialized { get { return(Attributes & FieldAttributes.NotSerialized) != 0; } }
172
173         public bool IsSpecialName  { get { return(Attributes & FieldAttributes.SpecialName) != 0; } }
174
175         public bool IsPinvokeImpl { get { return(Attributes & FieldAttributes.PinvokeImpl) != 0; } }
176
177         public virtual bool IsSecurityCritical
178         {
179             get { return FieldHandle.IsSecurityCritical(); }
180         }
181
182         public virtual bool IsSecuritySafeCritical
183         {
184             get { return FieldHandle.IsSecuritySafeCritical(); }
185         }
186
187         public virtual bool IsSecurityTransparent
188         {
189             get { return FieldHandle.IsSecurityTransparent(); }
190         }
191
192         #endregion
193
194 #if !FEATURE_CORECLR
195         Type _FieldInfo.GetType()
196         {
197             return base.GetType();
198         }
199
200         void _FieldInfo.GetTypeInfoCount(out uint pcTInfo)
201         {
202             throw new NotImplementedException();
203         }
204
205         void _FieldInfo.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
206         {
207             throw new NotImplementedException();
208         }
209
210         void _FieldInfo.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
211         {
212             throw new NotImplementedException();
213         }
214
215         // If you implement this method, make sure to include _FieldInfo.Invoke in VM\DangerousAPIs.h and 
216         // include _FieldInfo in SystemDomain::IsReflectionInvocationMethod in AppDomain.cpp.
217         void _FieldInfo.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
218         {
219             throw new NotImplementedException();
220         }
221 #endif
222     }
223
224     [Serializable]
225     internal abstract class RuntimeFieldInfo : FieldInfo, ISerializable
226     {
227         #region Private Data Members
228         private BindingFlags m_bindingFlags;
229         protected RuntimeTypeCache m_reflectedTypeCache;
230         protected RuntimeType m_declaringType;        
231         #endregion
232
233         #region Constructor
234         protected RuntimeFieldInfo()
235         {
236             // Used for dummy head node during population
237         }
238         protected RuntimeFieldInfo(RuntimeTypeCache reflectedTypeCache, RuntimeType declaringType, BindingFlags bindingFlags)
239         {
240             m_bindingFlags = bindingFlags;
241             m_declaringType = declaringType;
242             m_reflectedTypeCache = reflectedTypeCache;
243         }
244         #endregion
245
246 #if FEATURE_REMOTING
247         #region Legacy Remoting Cache
248         // The size of CachedData is accounted for by BaseObjectWithCachedData in object.h.
249         // This member is currently being used by Remoting for caching remoting data. If you
250         // need to cache data here, talk to the Remoting team to work out a mechanism, so that
251         // both caching systems can happily work together.
252         private RemotingFieldCachedData m_cachedData;
253
254         internal RemotingFieldCachedData RemotingCache
255         {
256             get
257             {
258                 // This grabs an internal copy of m_cachedData and uses
259                 // that instead of looking at m_cachedData directly because
260                 // the cache may get cleared asynchronously.  This prevents
261                 // us from having to take a lock.
262                 RemotingFieldCachedData cache = m_cachedData;
263                 if (cache == null)
264                 {
265                     cache = new RemotingFieldCachedData(this);
266                     RemotingFieldCachedData ret = Interlocked.CompareExchange(ref m_cachedData, cache, null);
267                     if (ret != null)
268                         cache = ret;
269                 }
270                 return cache;
271             }
272         }
273         #endregion
274 #endif //FEATURE_REMOTING
275
276         #region NonPublic Members
277         internal BindingFlags BindingFlags { get { return m_bindingFlags; } }
278         private RuntimeType ReflectedTypeInternal
279         { 
280             get 
281             { 
282                 return m_reflectedTypeCache.GetRuntimeType(); 
283             } 
284         }
285
286         internal RuntimeType GetDeclaringTypeInternal()
287         {
288             return m_declaringType;
289         }
290
291         internal RuntimeType GetRuntimeType() { return m_declaringType; }
292         internal abstract RuntimeModule GetRuntimeModule();
293         #endregion
294
295         #region MemberInfo Overrides
296         public override MemberTypes MemberType { get { return MemberTypes.Field; } }
297         public override Type ReflectedType
298         {
299             get
300             {
301                 return m_reflectedTypeCache.IsGlobal ? null : ReflectedTypeInternal;
302             }
303         }
304         
305         public override Type DeclaringType 
306         { 
307             get 
308             { 
309                 return m_reflectedTypeCache.IsGlobal ? null : m_declaringType; 
310             } 
311         }
312         
313         public override Module Module { get { return GetRuntimeModule(); } }
314         #endregion
315
316         #region Object Overrides
317         public unsafe override String ToString() 
318         {
319             if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8)
320                 return FieldType.ToString() + " " + Name;
321             else
322                 return FieldType.FormatTypeName() + " " + Name;
323         }
324         #endregion
325
326         #region ICustomAttributeProvider
327         public override Object[] GetCustomAttributes(bool inherit)
328         {
329             return CustomAttribute.GetCustomAttributes(this, typeof(object) as RuntimeType);
330         }
331
332         public override Object[] GetCustomAttributes(Type attributeType, bool inherit)
333         {
334             if (attributeType == null)
335                 throw new ArgumentNullException("attributeType");
336             Contract.EndContractBlock();
337
338             RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType;
339
340             if (attributeRuntimeType == null) 
341                 throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType");
342
343             return CustomAttribute.GetCustomAttributes(this, attributeRuntimeType);
344         }
345
346         [System.Security.SecuritySafeCritical]  // auto-generated
347         public override bool IsDefined(Type attributeType, bool inherit)
348         {
349             if (attributeType == null)
350                 throw new ArgumentNullException("attributeType");
351             Contract.EndContractBlock();
352
353             RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType;
354
355             if (attributeRuntimeType == null) 
356                 throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType");
357
358             return CustomAttribute.IsDefined(this, attributeRuntimeType);
359         }
360
361         public override IList<CustomAttributeData> GetCustomAttributesData()
362         {
363             return CustomAttributeData.GetCustomAttributesInternal(this);
364         }
365         #endregion
366
367         #region FieldInfo Overrides
368         // All implemented on derived classes
369         #endregion
370
371         #region ISerializable Implementation
372         [System.Security.SecurityCritical]  // auto-generated
373         public void GetObjectData(SerializationInfo info, StreamingContext context)
374         {
375             if (info == null)
376                 throw new ArgumentNullException("info");
377             Contract.EndContractBlock();
378             MemberInfoSerializationHolder.GetSerializationInfo(
379                 info,
380                 Name,
381                 ReflectedTypeInternal,
382                 ToString(),
383                 MemberTypes.Field);
384         }
385         #endregion
386     }
387
388     [Serializable]
389     internal unsafe sealed class RtFieldInfo : RuntimeFieldInfo, IRuntimeFieldInfo
390     {
391         #region FCalls
392         [System.Security.SecurityCritical]  // auto-generated
393         [System.Runtime.Versioning.ResourceExposure(System.Runtime.Versioning.ResourceScope.None)]
394         [MethodImplAttribute(MethodImplOptions.InternalCall)]
395         static private extern void PerformVisibilityCheckOnField(IntPtr field, Object target, RuntimeType declaringType, FieldAttributes attr, uint invocationFlags);
396         #endregion
397
398         #region Private Data Members
399         // agressive caching
400         private IntPtr m_fieldHandle;
401         private FieldAttributes m_fieldAttributes;
402         // lazy caching
403         private string m_name;
404         private RuntimeType m_fieldType;
405         private INVOCATION_FLAGS m_invocationFlags;
406
407 #if FEATURE_APPX
408         private bool IsNonW8PFrameworkAPI()
409         {
410             if (GetRuntimeType().IsNonW8PFrameworkAPI())
411                 return true;
412
413             // Allow "value__"
414             if (m_declaringType.IsEnum)
415                 return false;
416
417             RuntimeAssembly rtAssembly = GetRuntimeAssembly();
418             if (rtAssembly.IsFrameworkAssembly())
419             {
420                 int ctorToken = rtAssembly.InvocableAttributeCtorToken;
421                 if (System.Reflection.MetadataToken.IsNullToken(ctorToken) ||
422                     !CustomAttribute.IsAttributeDefined(GetRuntimeModule(), MetadataToken, ctorToken))
423                     return true;
424             }
425
426             return false;
427         }
428 #endif
429
430         internal INVOCATION_FLAGS InvocationFlags
431         {
432             get
433             {
434                 if ((m_invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED) == 0)
435                 {
436                     Type declaringType = DeclaringType;
437                     bool fIsReflectionOnlyType = (declaringType is ReflectionOnlyType);
438
439                     INVOCATION_FLAGS invocationFlags = 0;
440
441                     // first take care of all the NO_INVOKE cases
442                     if (
443                         (declaringType != null && declaringType.ContainsGenericParameters) ||
444                         (declaringType == null && Module.Assembly.ReflectionOnly) ||
445                         (fIsReflectionOnlyType)
446                        )
447                     {
448                         invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE;
449                     }
450
451                     // If the invocationFlags are still 0, then
452                     // this should be an usable field, determine the other flags 
453                     if (invocationFlags == 0)
454                     {
455                         if ((m_fieldAttributes & FieldAttributes.InitOnly) != (FieldAttributes)0)
456                             invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_SPECIAL_FIELD;
457
458                         if ((m_fieldAttributes & FieldAttributes.HasFieldRVA) != (FieldAttributes)0)
459                             invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_SPECIAL_FIELD;
460
461                         // A public field is inaccesible to Transparent code if the field is Critical.
462                         bool needsTransparencySecurityCheck = IsSecurityCritical && !IsSecuritySafeCritical;
463                         bool needsVisibilitySecurityCheck = ((m_fieldAttributes & FieldAttributes.FieldAccessMask) != FieldAttributes.Public) ||
464                                                             (declaringType != null && declaringType.NeedsReflectionSecurityCheck);
465                         if (needsTransparencySecurityCheck || needsVisibilitySecurityCheck)
466                             invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY;
467
468                         // find out if the field type is one of the following: Primitive, Enum or Pointer
469                         Type fieldType = FieldType;
470                         if (fieldType.IsPointer || fieldType.IsEnum || fieldType.IsPrimitive)
471                             invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_FIELD_SPECIAL_CAST;
472                     }
473
474 #if FEATURE_APPX
475                     if (AppDomain.ProfileAPICheck && IsNonW8PFrameworkAPI())
476                         invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API;
477 #endif // FEATURE_APPX
478
479                     // must be last to avoid threading problems
480                     m_invocationFlags = invocationFlags | INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED;
481                 }
482
483                 return m_invocationFlags;
484             }
485         }
486         #endregion
487
488         private RuntimeAssembly GetRuntimeAssembly() { return m_declaringType.GetRuntimeAssembly(); }
489
490         #region Constructor
491         [System.Security.SecurityCritical]  // auto-generated
492         internal RtFieldInfo(
493             RuntimeFieldHandleInternal handle, RuntimeType declaringType, RuntimeTypeCache reflectedTypeCache, BindingFlags bindingFlags) 
494             : base(reflectedTypeCache, declaringType, bindingFlags)
495         {
496             m_fieldHandle = handle.Value;
497             m_fieldAttributes = RuntimeFieldHandle.GetAttributes(handle);
498         }
499         #endregion
500
501         #region Private Members
502         RuntimeFieldHandleInternal IRuntimeFieldInfo.Value
503         {
504             [System.Security.SecuritySafeCritical]
505             get
506             {
507                 return new RuntimeFieldHandleInternal(m_fieldHandle);
508             }
509         }
510
511         #endregion
512
513         #region Internal Members
514         internal void CheckConsistency(Object target) 
515         {
516             // only test instance fields
517             if ((m_fieldAttributes & FieldAttributes.Static) != FieldAttributes.Static) 
518             {
519                 if (!m_declaringType.IsInstanceOfType(target))
520                 {
521                     if (target == null)
522                     {
523 #if FEATURE_LEGACYNETCF
524                         if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8)
525                             throw new ArgumentNullException(Environment.GetResourceString("RFLCT.Targ_StatFldReqTarg"));
526                         else
527 #endif
528                         throw new TargetException(Environment.GetResourceString("RFLCT.Targ_StatFldReqTarg"));
529                     }
530                     else
531                     {
532                         throw new ArgumentException(
533                             String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Arg_FieldDeclTarget"),
534                                 Name, m_declaringType, target.GetType()));
535                     }
536                 }
537             }
538         }
539
540         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
541         internal override bool CacheEquals(object o)
542         {
543             RtFieldInfo m = o as RtFieldInfo;
544
545             if ((object)m == null)
546                 return false;
547
548             return m.m_fieldHandle == m_fieldHandle;
549         }
550
551         [System.Security.SecurityCritical]
552         [DebuggerStepThroughAttribute]
553         [Diagnostics.DebuggerHidden]
554         internal void InternalSetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture, ref StackCrawlMark stackMark)
555         {
556             INVOCATION_FLAGS invocationFlags = InvocationFlags;
557             RuntimeType declaringType = DeclaringType as RuntimeType;
558
559             if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE) != 0)
560             {
561                 if (declaringType != null && declaringType.ContainsGenericParameters)
562                     throw new InvalidOperationException(Environment.GetResourceString("Arg_UnboundGenField"));
563
564                 if ((declaringType == null && Module.Assembly.ReflectionOnly) || declaringType is ReflectionOnlyType)
565                     throw new InvalidOperationException(Environment.GetResourceString("Arg_ReflectionOnlyField"));
566
567                 throw new FieldAccessException();
568             }
569
570             CheckConsistency(obj);
571
572             RuntimeType fieldType = (RuntimeType)FieldType;
573             value = fieldType.CheckValue(value, binder, culture, invokeAttr);
574
575             #region Security Check
576 #if FEATURE_APPX
577             if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0)
578             {
579                 RuntimeAssembly caller = RuntimeAssembly.GetExecutingAssembly(ref stackMark);
580                 if (caller != null && !caller.IsSafeForReflection())
581                     throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", FullName));
582             }
583 #endif
584
585             if ((invocationFlags & (INVOCATION_FLAGS.INVOCATION_FLAGS_SPECIAL_FIELD | INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY)) != 0) 
586                 PerformVisibilityCheckOnField(m_fieldHandle, obj, m_declaringType, m_fieldAttributes, (uint)m_invocationFlags);
587             #endregion
588
589             bool domainInitialized = false;
590             if (declaringType == null)
591             {
592                 RuntimeFieldHandle.SetValue(this, obj, value, fieldType, m_fieldAttributes, null, ref domainInitialized);
593             }
594             else
595             {
596                 domainInitialized = declaringType.DomainInitialized;
597                 RuntimeFieldHandle.SetValue(this, obj, value, fieldType, m_fieldAttributes, declaringType, ref domainInitialized);
598                 declaringType.DomainInitialized = domainInitialized;
599             }
600         }
601
602         // UnsafeSetValue doesn't perform any consistency or visibility check.
603         // It is the caller's responsibility to ensure the operation is safe.
604         // When the caller needs to perform visibility checks they should call
605         // InternalSetValue() instead. When the caller needs to perform 
606         // consistency checks they should call CheckConsistency() before 
607         // calling this method.
608         [System.Security.SecurityCritical]  // auto-generated
609         [DebuggerStepThroughAttribute]
610         [Diagnostics.DebuggerHidden]
611         internal void UnsafeSetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture)
612         {
613             RuntimeType declaringType = DeclaringType as RuntimeType;
614             RuntimeType fieldType = (RuntimeType)FieldType;
615             value = fieldType.CheckValue(value, binder, culture, invokeAttr);
616
617             bool domainInitialized = false;
618             if (declaringType == null)
619             {
620                 RuntimeFieldHandle.SetValue(this, obj, value, fieldType, m_fieldAttributes, null, ref domainInitialized);
621             }
622             else
623             {
624                 domainInitialized = declaringType.DomainInitialized;
625                 RuntimeFieldHandle.SetValue(this, obj, value, fieldType, m_fieldAttributes, declaringType, ref domainInitialized);
626                 declaringType.DomainInitialized = domainInitialized;
627             }
628         }
629
630         [System.Security.SecuritySafeCritical]
631         [DebuggerStepThroughAttribute]
632         [Diagnostics.DebuggerHidden]
633         internal Object InternalGetValue(Object obj, ref StackCrawlMark stackMark)
634         {
635             INVOCATION_FLAGS invocationFlags = InvocationFlags;
636             RuntimeType declaringType = DeclaringType as RuntimeType;
637
638             if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE) != 0)
639             {
640                 if (declaringType != null && DeclaringType.ContainsGenericParameters)
641                     throw new InvalidOperationException(Environment.GetResourceString("Arg_UnboundGenField"));
642
643                 if ((declaringType == null && Module.Assembly.ReflectionOnly) || declaringType is ReflectionOnlyType)
644                     throw new InvalidOperationException(Environment.GetResourceString("Arg_ReflectionOnlyField"));
645
646                 throw new FieldAccessException();
647             }
648
649             CheckConsistency(obj);
650
651 #if FEATURE_APPX
652             if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0)
653             {
654                 RuntimeAssembly caller = RuntimeAssembly.GetExecutingAssembly(ref stackMark);
655                 if (caller != null && !caller.IsSafeForReflection())
656                     throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", FullName));
657             }
658 #endif
659
660             RuntimeType fieldType = (RuntimeType)FieldType;
661             if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY) != 0)
662                 PerformVisibilityCheckOnField(m_fieldHandle, obj, m_declaringType, m_fieldAttributes, (uint)(m_invocationFlags & ~INVOCATION_FLAGS.INVOCATION_FLAGS_SPECIAL_FIELD));
663
664             return UnsafeGetValue(obj);
665         }
666
667         // UnsafeGetValue doesn't perform any consistency or visibility check.
668         // It is the caller's responsibility to ensure the operation is safe.
669         // When the caller needs to perform visibility checks they should call
670         // InternalGetValue() instead. When the caller needs to perform 
671         // consistency checks they should call CheckConsistency() before 
672         // calling this method.
673         [System.Security.SecurityCritical]
674         [DebuggerStepThroughAttribute]
675         [Diagnostics.DebuggerHidden]
676         internal Object UnsafeGetValue(Object obj)
677         {
678             RuntimeType declaringType = DeclaringType as RuntimeType;
679
680             RuntimeType fieldType = (RuntimeType)FieldType;
681
682             bool domainInitialized = false;
683             if (declaringType == null)
684             {
685                 return RuntimeFieldHandle.GetValue(this, obj, fieldType, null, ref domainInitialized);
686             }
687             else
688             {
689                 domainInitialized = declaringType.DomainInitialized;
690                 object retVal = RuntimeFieldHandle.GetValue(this, obj, fieldType, declaringType, ref domainInitialized);
691                 declaringType.DomainInitialized = domainInitialized;
692                 return retVal;
693             }               
694         } 
695
696         #endregion
697
698         #region MemberInfo Overrides
699         public override String Name 
700         {
701             [System.Security.SecuritySafeCritical]  // auto-generated
702             get
703             {
704                 if (m_name == null)
705                     m_name = RuntimeFieldHandle.GetName(this);
706
707                 return m_name;
708             }
709         }
710
711         internal String FullName
712         {
713             get
714             {
715                 return String.Format("{0}.{1}", DeclaringType.FullName, Name);
716             }
717         }
718
719         public override int MetadataToken
720         {
721             [System.Security.SecuritySafeCritical]  // auto-generated
722             get { return RuntimeFieldHandle.GetToken(this); }
723         }
724
725         [System.Security.SecuritySafeCritical]  // auto-generated
726         internal override RuntimeModule GetRuntimeModule()
727         {
728             return RuntimeTypeHandle.GetModule(RuntimeFieldHandle.GetApproxDeclaringType(this));
729         }
730
731         #endregion
732
733         #region FieldInfo Overrides        
734         public override Object GetValue(Object obj)
735         {
736             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
737             return InternalGetValue(obj, ref stackMark);
738         } 
739         
740         public override object GetRawConstantValue() { throw new InvalidOperationException(); }
741
742         [System.Security.SecuritySafeCritical]  // auto-generated
743         [DebuggerStepThroughAttribute]
744         [Diagnostics.DebuggerHidden]
745         public override Object GetValueDirect(TypedReference obj)
746         {
747             if (obj.IsNull)
748                 throw new ArgumentException(Environment.GetResourceString("Arg_TypedReference_Null"));
749             Contract.EndContractBlock();
750
751             unsafe
752             {
753                 // Passing TypedReference by reference is easier to make correct in native code
754                 return RuntimeFieldHandle.GetValueDirect(this, (RuntimeType)FieldType, &obj, (RuntimeType)DeclaringType);
755             }
756         }
757
758         [System.Security.SecuritySafeCritical]  // auto-generated
759         [DebuggerStepThroughAttribute]
760         [Diagnostics.DebuggerHidden]
761         public override void SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture)
762         {
763             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
764             InternalSetValue(obj, value, invokeAttr, binder, culture, ref stackMark);
765         }
766
767         [System.Security.SecuritySafeCritical]  // auto-generated
768         [DebuggerStepThroughAttribute]
769         [Diagnostics.DebuggerHidden]
770         public override void SetValueDirect(TypedReference obj, Object value)
771         {
772             if (obj.IsNull)
773                 throw new ArgumentException(Environment.GetResourceString("Arg_TypedReference_Null"));
774             Contract.EndContractBlock();
775
776             unsafe
777             {
778                 // Passing TypedReference by reference is easier to make correct in native code
779                 RuntimeFieldHandle.SetValueDirect(this, (RuntimeType)FieldType, &obj, value, (RuntimeType)DeclaringType);
780             }
781         }
782
783         public override RuntimeFieldHandle FieldHandle 
784         {
785             get
786             {
787                 Type declaringType = DeclaringType;
788                 if ((declaringType == null && Module.Assembly.ReflectionOnly) || declaringType is ReflectionOnlyType)
789                     throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotAllowedInReflectionOnly"));
790                 return new RuntimeFieldHandle(this);
791             }
792         }
793
794         internal IntPtr GetFieldHandle() 
795         {
796             return m_fieldHandle;
797         }
798
799         public override FieldAttributes Attributes 
800         {
801             get
802             {
803                 return m_fieldAttributes;
804             }
805         }
806
807         public override Type FieldType 
808         {
809             [System.Security.SecuritySafeCritical]  // auto-generated
810             get
811             {
812                 if (m_fieldType == null)
813                     m_fieldType = new Signature(this, m_declaringType).FieldType;
814
815                 return m_fieldType;
816             }
817         }       
818         
819         [System.Security.SecuritySafeCritical]  // auto-generated
820         public override Type[] GetRequiredCustomModifiers()
821         {
822             return new Signature(this, m_declaringType).GetCustomModifiers(1, true);
823         }
824
825         [System.Security.SecuritySafeCritical]  // auto-generated
826         public override Type[] GetOptionalCustomModifiers()
827         {
828             return new Signature(this, m_declaringType).GetCustomModifiers(1, false);
829         }
830
831         #endregion
832     }
833
834     [Serializable]
835     internal sealed unsafe class MdFieldInfo : RuntimeFieldInfo, ISerializable
836     {
837         #region Private Data Members
838         private int m_tkField;
839         private string m_name;
840         private RuntimeType m_fieldType;
841         private FieldAttributes m_fieldAttributes;
842         #endregion
843
844         #region Constructor
845         internal MdFieldInfo(
846         int tkField, FieldAttributes fieldAttributes, RuntimeTypeHandle declaringTypeHandle, RuntimeTypeCache reflectedTypeCache, BindingFlags bindingFlags)
847             : base(reflectedTypeCache, declaringTypeHandle.GetRuntimeType(), bindingFlags)
848         {
849             m_tkField = tkField;
850             m_name = null; 
851             m_fieldAttributes = fieldAttributes;
852         }
853         #endregion
854
855         #region Internal Members
856         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
857         internal override bool CacheEquals(object o)
858         {
859             MdFieldInfo m = o as MdFieldInfo;
860
861             if ((object)m == null)
862                 return false;
863
864             return m.m_tkField == m_tkField && 
865                 m_declaringType.GetTypeHandleInternal().GetModuleHandle().Equals(
866                     m.m_declaringType.GetTypeHandleInternal().GetModuleHandle());
867         }
868         #endregion
869
870         #region MemberInfo Overrides
871         public override String Name 
872         {
873             [System.Security.SecuritySafeCritical]  // auto-generated
874             get
875             {
876                 if (m_name == null)
877                     m_name = GetRuntimeModule().MetadataImport.GetName(m_tkField).ToString();
878
879                 return m_name;
880             }
881         }
882
883         public override int MetadataToken { get { return m_tkField; } }
884         internal override RuntimeModule GetRuntimeModule() { return m_declaringType.GetRuntimeModule(); }
885         #endregion
886
887         #region FieldInfo Overrides
888         public override RuntimeFieldHandle FieldHandle { get { throw new NotSupportedException(); } }
889         public override FieldAttributes Attributes { get { return m_fieldAttributes; } }
890
891         public override bool IsSecurityCritical { get { return DeclaringType.IsSecurityCritical; } }
892         public override bool IsSecuritySafeCritical { get { return DeclaringType.IsSecuritySafeCritical; } }
893         public override bool IsSecurityTransparent { get { return DeclaringType.IsSecurityTransparent; } }
894
895         [DebuggerStepThroughAttribute]
896         [Diagnostics.DebuggerHidden]
897         public override Object GetValueDirect(TypedReference obj)
898         {
899             return GetValue(null);
900         }
901
902         [DebuggerStepThroughAttribute]
903         [Diagnostics.DebuggerHidden]
904         public override void SetValueDirect(TypedReference obj,Object value)
905         {
906             throw new FieldAccessException(Environment.GetResourceString("Acc_ReadOnly"));
907         }
908
909         [DebuggerStepThroughAttribute]
910         [Diagnostics.DebuggerHidden]
911         public unsafe override Object GetValue(Object obj)
912         {
913             return GetValue(false);
914         }
915
916         public unsafe override Object GetRawConstantValue() { return GetValue(true); }
917         
918         [System.Security.SecuritySafeCritical]  // auto-generated
919         private unsafe Object GetValue(bool raw)
920         {
921             // Cannot cache these because they could be user defined non-agile enumerations
922
923             Object value = MdConstant.GetValue(GetRuntimeModule().MetadataImport, m_tkField, FieldType.GetTypeHandleInternal(), raw);
924
925             if (value == DBNull.Value)
926                 throw new NotSupportedException(Environment.GetResourceString("Arg_EnumLitValueNotFound"));
927
928             return value;
929         } 
930
931         [DebuggerStepThroughAttribute]
932         [Diagnostics.DebuggerHidden]
933         public override void SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture)
934         {
935             throw new FieldAccessException(Environment.GetResourceString("Acc_ReadOnly"));
936         }
937
938         public override Type FieldType 
939         {
940             [System.Security.SecuritySafeCritical]  // auto-generated
941             get
942             {
943                 if (m_fieldType == null)
944                 {
945                     ConstArray fieldMarshal = GetRuntimeModule().MetadataImport.GetSigOfFieldDef(m_tkField);
946
947                     m_fieldType = new Signature(fieldMarshal.Signature.ToPointer(), 
948                         (int)fieldMarshal.Length, m_declaringType).FieldType;
949                 }
950
951                 return m_fieldType;
952             }
953         }       
954     
955         public override Type[] GetRequiredCustomModifiers()
956         {
957             return EmptyArray<Type>.Value;
958         }
959
960         public override Type[] GetOptionalCustomModifiers()
961         {
962             return EmptyArray<Type>.Value;
963         }
964
965         #endregion
966     }
967
968 }