Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / mscorlib / system / reflection / parameterinfo.cs
1 // ==++==
2 // 
3 //   Copyright(c) Microsoft Corporation.  All rights reserved.
4 // 
5 // ==--==
6 // <OWNER>[....]</OWNER>
7 // 
8
9 namespace System.Reflection
10 {
11     using System;
12     using System.Collections.Generic;
13     using System.Diagnostics.Contracts;
14     using System.Runtime.InteropServices;
15     using System.Runtime.Serialization;
16     using System.Runtime.CompilerServices;
17 #if FEATURE_REMOTING
18     using System.Runtime.Remoting.Metadata;
19 #endif //FEATURE_REMOTING
20     using System.Security.Permissions;
21     using System.Threading;
22     using MdToken = System.Reflection.MetadataToken;
23
24     [Serializable]
25     [ClassInterface(ClassInterfaceType.None)]
26     [ComDefaultInterface(typeof(_ParameterInfo))]
27     [System.Runtime.InteropServices.ComVisible(true)]
28     public class ParameterInfo : _ParameterInfo, ICustomAttributeProvider, IObjectReference
29     {
30         #region Legacy Protected Members
31         protected String NameImpl; 
32         protected Type ClassImpl; 
33         protected int PositionImpl; 
34         protected ParameterAttributes AttrsImpl; 
35         protected Object DefaultValueImpl; // cannot cache this as it may be non agile user defined enum
36         protected MemberInfo MemberImpl;
37         #endregion
38
39         #region Legacy Private Members
40         // These are here only for backwards compatibility -- they are not set
41         // until this instance is serialized, so don't rely on their values from
42         // arbitrary code.
43 #pragma warning disable 169
44         [OptionalField]
45         private IntPtr _importer;
46         [OptionalField]
47         private int _token;
48         [OptionalField]
49         private bool bExtraConstChecked;
50 #pragma warning restore 169
51         #endregion
52
53         #region Constructor
54         protected ParameterInfo() 
55         { 
56         }         
57         #endregion
58
59         #region Internal Members
60         // this is an internal api for DynamicMethod. A better solution is to change the relationship
61         // between ParameterInfo and ParameterBuilder so that a ParameterBuilder can be seen as a writer
62         // api over a ParameterInfo. However that is a possible breaking change so it needs to go through some process first
63         internal void SetName(String name) 
64         {
65             NameImpl = name;
66         }
67         
68         internal void SetAttributes(ParameterAttributes attributes) 
69         {
70             AttrsImpl = attributes;
71         }
72         #endregion
73
74         #region Public Methods
75         public virtual Type ParameterType 
76         { 
77             get 
78             {
79                 return ClassImpl;
80             } 
81         }            
82         
83         public virtual String Name 
84         { 
85             get 
86             {
87                 return NameImpl;
88             } 
89         }
90
91         public virtual bool HasDefaultValue { get { throw new NotImplementedException(); }  }
92
93         public virtual Object DefaultValue { get { throw new NotImplementedException(); } }
94         public virtual Object RawDefaultValue  { get { throw new NotImplementedException(); } } 
95
96         public virtual int Position { get { return PositionImpl; } }                                    
97         public virtual ParameterAttributes Attributes { get { return AttrsImpl; } }
98
99         public virtual MemberInfo Member {
100             get {
101                 Contract.Ensures(Contract.Result<MemberInfo>() != null);
102                 return MemberImpl;
103             }
104         }
105
106         public bool IsIn { get { return((Attributes & ParameterAttributes.In) != 0); } }        
107         public bool IsOut { get { return((Attributes & ParameterAttributes.Out) != 0); } }  
108 #if FEATURE_USE_LCID        
109         public bool IsLcid { get { return((Attributes & ParameterAttributes.Lcid) != 0); } }        
110 #endif
111         public bool IsRetval { get { return((Attributes & ParameterAttributes.Retval) != 0); } }        
112         public bool IsOptional { get { return((Attributes & ParameterAttributes.Optional) != 0); } }
113
114         public virtual int MetadataToken
115         {
116             get
117             {
118                 // This API was made virtual in V4. Code compiled against V2 might use
119                 // "call" rather than "callvirt" to call it.
120                 // This makes sure those code still works.
121                 RuntimeParameterInfo rtParam = this as RuntimeParameterInfo;
122                 if (rtParam != null)
123                     return rtParam.MetadataToken;
124
125                 // return a null token
126                 return (int)MetadataTokenType.ParamDef;
127             }
128         }
129
130         public virtual Type[] GetRequiredCustomModifiers() 
131         {
132             return EmptyArray<Type>.Value;
133         }
134
135         public virtual Type[] GetOptionalCustomModifiers() 
136         {
137             return EmptyArray<Type>.Value;
138         }
139         #endregion
140
141         #region Object Overrides
142         public override String ToString()
143         {
144             return ParameterType.FormatTypeName() + " " + Name;
145         }
146         #endregion
147
148         public virtual IEnumerable<CustomAttributeData> CustomAttributes
149         {
150             get
151             {
152                 return GetCustomAttributesData();
153             }
154         }
155         #region ICustomAttributeProvider
156         public virtual Object[] GetCustomAttributes(bool inherit)
157         {
158             return EmptyArray<Object>.Value;
159         }
160
161         public virtual Object[] GetCustomAttributes(Type attributeType, bool inherit)
162         {
163             if (attributeType == null)
164                 throw new ArgumentNullException("attributeType");
165             Contract.EndContractBlock();
166
167             return EmptyArray<Object>.Value;
168         }
169
170         public virtual bool IsDefined(Type attributeType, bool inherit)
171         {
172             if (attributeType == null)
173                 throw new ArgumentNullException("attributeType");
174             Contract.EndContractBlock();
175
176             return false;
177         }
178
179         public virtual IList<CustomAttributeData> GetCustomAttributesData()
180         {
181             throw new NotImplementedException();
182         }
183         #endregion
184
185         #region _ParameterInfo implementation
186
187 #if !FEATURE_CORECLR
188         void _ParameterInfo.GetTypeInfoCount(out uint pcTInfo)
189         {
190             throw new NotImplementedException();
191         }
192
193         void _ParameterInfo.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
194         {
195             throw new NotImplementedException();
196         }
197
198         void _ParameterInfo.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
199         {
200             throw new NotImplementedException();
201         }
202
203         void _ParameterInfo.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
204         {
205             throw new NotImplementedException();
206         }
207 #endif
208
209         #endregion
210
211         #region IObjectReference
212         // In V4 RuntimeParameterInfo is introduced. 
213         // To support deserializing ParameterInfo instances serialized in earlier versions
214         // we need to implement IObjectReference.
215         [System.Security.SecurityCritical]
216         public object GetRealObject(StreamingContext context)
217         {
218             Contract.Ensures(Contract.Result<Object>() != null);
219
220             // Once all the serializable fields have come in we can set up the real
221             // instance based on just two of them (MemberImpl and PositionImpl).
222
223             if (MemberImpl == null)
224                 throw new SerializationException(Environment.GetResourceString(ResId.Serialization_InsufficientState));
225
226             ParameterInfo[] args = null;
227
228             switch (MemberImpl.MemberType)
229             {
230                 case MemberTypes.Constructor:
231                 case MemberTypes.Method:
232                     if (PositionImpl == -1)
233                     {
234                         if (MemberImpl.MemberType == MemberTypes.Method)
235                             return ((MethodInfo)MemberImpl).ReturnParameter;
236                         else
237                             throw new SerializationException(Environment.GetResourceString(ResId.Serialization_BadParameterInfo));
238                     }
239                     else
240                     {
241                         args = ((MethodBase)MemberImpl).GetParametersNoCopy();
242
243                         if (args != null && PositionImpl < args.Length)
244                             return args[PositionImpl];
245                         else
246                             throw new SerializationException(Environment.GetResourceString(ResId.Serialization_BadParameterInfo));
247                     }
248
249                 case MemberTypes.Property:
250                     args = ((RuntimePropertyInfo)MemberImpl).GetIndexParametersNoCopy();
251
252                     if (args != null && PositionImpl > -1 && PositionImpl < args.Length)
253                         return args[PositionImpl];
254                     else
255                         throw new SerializationException(Environment.GetResourceString(ResId.Serialization_BadParameterInfo));
256
257                 default:
258                     throw new SerializationException(Environment.GetResourceString(ResId.Serialization_NoParameterInfo));
259             }
260         }
261         #endregion
262     }
263
264     [Serializable]
265     internal unsafe sealed class RuntimeParameterInfo : ParameterInfo, ISerializable
266     {
267         #region Static Members
268         [System.Security.SecurityCritical]  // auto-generated
269         internal unsafe static ParameterInfo[] GetParameters(IRuntimeMethodInfo method, MemberInfo member, Signature sig)
270         {
271             Contract.Assert(method is RuntimeMethodInfo || method is RuntimeConstructorInfo);
272
273             ParameterInfo dummy;
274             return GetParameters(method, member, sig, out dummy, false);
275         }
276
277         [System.Security.SecurityCritical]  // auto-generated
278         internal unsafe static ParameterInfo GetReturnParameter(IRuntimeMethodInfo method, MemberInfo member, Signature sig)
279         {
280             Contract.Assert(method is RuntimeMethodInfo || method is RuntimeConstructorInfo);
281
282             ParameterInfo returnParameter;
283             GetParameters(method, member, sig, out returnParameter, true);
284             return returnParameter;
285         }
286
287         [System.Security.SecurityCritical]  // auto-generated
288         internal unsafe static ParameterInfo[] GetParameters(
289             IRuntimeMethodInfo methodHandle, MemberInfo member, Signature sig, out ParameterInfo returnParameter, bool fetchReturnParameter)
290         {
291             returnParameter = null;
292             int sigArgCount = sig.Arguments.Length;
293             ParameterInfo[] args = fetchReturnParameter ? null : new ParameterInfo[sigArgCount];
294
295             int tkMethodDef = RuntimeMethodHandle.GetMethodDef(methodHandle);
296             int cParamDefs = 0;
297
298             // Not all methods have tokens. Arrays, pointers and byRef types do not have tokens as they
299             // are generated on the fly by the runtime. 
300             if (!MdToken.IsNullToken(tkMethodDef))
301             {
302                 MetadataImport scope = RuntimeTypeHandle.GetMetadataImport(RuntimeMethodHandle.GetDeclaringType(methodHandle));
303
304                 MetadataEnumResult tkParamDefs;
305                 scope.EnumParams(tkMethodDef, out tkParamDefs);
306
307                 cParamDefs = tkParamDefs.Length;
308
309                 // Not all parameters have tokens. Parameters may have no token 
310                 // if they have no name and no attributes.
311                 if (cParamDefs > sigArgCount + 1 /* return type */)
312                     throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ParameterSignatureMismatch"));
313
314                 for (int i = 0; i < cParamDefs; i++)
315                 {
316                     #region Populate ParameterInfos
317                     ParameterAttributes attr;
318                     int position, tkParamDef = tkParamDefs[i];
319
320                     scope.GetParamDefProps(tkParamDef, out position, out attr);
321
322                     position--;
323
324                     if (fetchReturnParameter == true && position == -1)
325                     {
326                         // more than one return parameter?
327                         if (returnParameter != null)
328                             throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ParameterSignatureMismatch"));
329
330                         returnParameter = new RuntimeParameterInfo(sig, scope, tkParamDef, position, attr, member);
331                     }
332                     else if (fetchReturnParameter == false && position >= 0)
333                     {
334                         // position beyong sigArgCount?
335                         if (position >= sigArgCount)
336                             throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ParameterSignatureMismatch"));
337
338                         args[position] = new RuntimeParameterInfo(sig, scope, tkParamDef, position, attr, member);
339                     }
340                     #endregion
341                 }
342             }
343
344             // Fill in empty ParameterInfos for those without tokens
345             if (fetchReturnParameter)
346             {
347                 if (returnParameter == null)
348                 {
349                     returnParameter = new RuntimeParameterInfo(sig, MetadataImport.EmptyImport, 0, -1, (ParameterAttributes)0, member);
350                 }
351             }
352             else
353             {
354                 if (cParamDefs < args.Length + 1)
355                 {
356                     for (int i = 0; i < args.Length; i++)
357                     {
358                         if (args[i] != null)
359                             continue;
360
361                         args[i] = new RuntimeParameterInfo(sig, MetadataImport.EmptyImport, 0, i, (ParameterAttributes)0, member);
362                     }
363                 }
364             }
365
366             return args;
367         }
368         #endregion
369
370         #region Private Statics
371         private static readonly Type s_DecimalConstantAttributeType = typeof(DecimalConstantAttribute);
372         private static readonly Type s_CustomConstantAttributeType = typeof(CustomConstantAttribute);
373         #endregion
374
375         #region Private Data Members
376         // These are new in Whidbey, so we cannot serialize them directly or we break backwards compatibility.
377         [NonSerialized]
378         private int m_tkParamDef;
379         [NonSerialized]
380         private MetadataImport m_scope;
381         [NonSerialized]
382         private Signature m_signature;
383         [NonSerialized]
384         private volatile bool m_nameIsCached = false;
385         [NonSerialized]
386         private readonly bool m_noMetadata = false;
387         [NonSerialized]
388         private bool m_noDefaultValue = false;
389         [NonSerialized]
390         private MethodBase m_originalMember = null;
391         #endregion
392
393         #region Internal Properties
394         internal MethodBase DefiningMethod
395         {
396             get
397             {
398                 MethodBase result = m_originalMember != null ? m_originalMember : MemberImpl as MethodBase;
399                 Contract.Assert(result != null);
400                 return result;
401             }
402         }
403         #endregion
404
405         #region VTS magic to serialize/deserialized to/from pre-Whidbey endpoints.
406         [System.Security.SecurityCritical]
407         public void GetObjectData(SerializationInfo info, StreamingContext context)
408         {
409             if (info == null)
410                 throw new ArgumentNullException("info");
411             Contract.EndContractBlock();
412
413             // We could be serializing for consumption by a pre-Whidbey
414             // endpoint. Therefore we set up all the serialized fields to look
415             // just like a v1.0/v1.1 instance.
416
417             // Need to set the type to ParameterInfo so that pre-Whidbey and Whidbey code
418             // can deserialize this. This is also why we cannot simply use [OnSerializing].
419             info.SetType(typeof(ParameterInfo));
420
421             // Use the properties intead of the fields in case the fields haven't been et
422             // _importer, bExtraConstChecked, and m_cachedData don't need to be set
423
424             // Now set the legacy fields that the current implementation doesn't
425             // use any more. Note that _importer is a raw pointer that should
426             // never have been serialized in V1. We set it to zero here; if the
427             // deserializer uses it (by calling GetCustomAttributes() on this
428             // instance) they'll AV, but at least it will be a well defined
429             // exception and not a random AV.
430
431             info.AddValue("AttrsImpl", Attributes);
432             info.AddValue("ClassImpl", ParameterType);
433             info.AddValue("DefaultValueImpl", DefaultValue);
434             info.AddValue("MemberImpl", Member);
435             info.AddValue("NameImpl", Name);
436             info.AddValue("PositionImpl", Position);
437             info.AddValue("_token", m_tkParamDef);
438         }
439         #endregion
440
441         #region Constructor
442         // used by RuntimePropertyInfo
443         internal RuntimeParameterInfo(RuntimeParameterInfo accessor, RuntimePropertyInfo property)
444             : this(accessor, (MemberInfo)property)
445         {
446             m_signature = property.Signature;
447         }
448
449         private RuntimeParameterInfo(RuntimeParameterInfo accessor, MemberInfo member)
450         {
451             // Change ownership
452             MemberImpl = member;
453             
454             // The original owner should always be a method, because this method is only used to 
455             // change the owner from a method to a property.
456             m_originalMember = accessor.MemberImpl as MethodBase;
457             Contract.Assert(m_originalMember != null);
458
459             // Populate all the caches -- we inherit this behavior from RTM
460             NameImpl = accessor.Name;
461             m_nameIsCached = true;
462             ClassImpl = accessor.ParameterType;
463             PositionImpl = accessor.Position;
464             AttrsImpl = accessor.Attributes;
465
466             // Strictly speeking, property's don't contain paramter tokens
467             // However we need this to make ca's work... oh well...
468             m_tkParamDef = MdToken.IsNullToken(accessor.MetadataToken) ? (int)MetadataTokenType.ParamDef : accessor.MetadataToken;
469             m_scope = accessor.m_scope;
470         }
471
472         private RuntimeParameterInfo(
473             Signature signature, MetadataImport scope, int tkParamDef,
474             int position, ParameterAttributes attributes, MemberInfo member)
475         {
476             Contract.Requires(member != null);
477             Contract.Assert(MdToken.IsNullToken(tkParamDef) == scope.Equals(MetadataImport.EmptyImport));
478             Contract.Assert(MdToken.IsNullToken(tkParamDef) || MdToken.IsTokenOfType(tkParamDef, MetadataTokenType.ParamDef));
479
480             PositionImpl = position;
481             MemberImpl = member;
482             m_signature = signature;
483             m_tkParamDef = MdToken.IsNullToken(tkParamDef) ? (int)MetadataTokenType.ParamDef : tkParamDef;
484             m_scope = scope;
485             AttrsImpl = attributes;
486
487             ClassImpl = null;
488             NameImpl = null;
489         }
490
491         // ctor for no metadata MethodInfo in the DynamicMethod and RuntimeMethodInfo cases
492         internal RuntimeParameterInfo(MethodInfo owner, String name, Type parameterType, int position)
493         {
494             MemberImpl = owner;
495             NameImpl = name;
496             m_nameIsCached = true;
497             m_noMetadata = true;
498             ClassImpl = parameterType;
499             PositionImpl = position;
500             AttrsImpl = ParameterAttributes.None;
501             m_tkParamDef = (int)MetadataTokenType.ParamDef;
502             m_scope = MetadataImport.EmptyImport;
503         }
504         #endregion
505
506         #region Public Methods
507         public override Type ParameterType
508         {
509             get
510             {
511                 // only instance of ParameterInfo has ClassImpl, all its subclasses don't
512                 if (ClassImpl == null)
513                 {
514                     RuntimeType parameterType;
515                     if (PositionImpl == -1)
516                         parameterType = m_signature.ReturnType;
517                     else
518                         parameterType = m_signature.Arguments[PositionImpl];
519
520                     Contract.Assert(parameterType != null);
521                     // different thread could only write ClassImpl to the same value, so ---- is not a problem here
522                     ClassImpl = parameterType;
523                 }
524
525                 return ClassImpl;
526             }
527         }
528
529         public override String Name
530         {
531             [System.Security.SecuritySafeCritical]  // auto-generated
532             get
533             {
534                 if (!m_nameIsCached)
535                 {
536                     if (!MdToken.IsNullToken(m_tkParamDef))
537                     {
538                         string name;
539                         name = m_scope.GetName(m_tkParamDef).ToString();
540                         NameImpl = name;
541                     }
542
543                     // other threads could only write it to true, so ---- is OK
544                     // this field is volatile, so the write ordering is guaranteed
545                     m_nameIsCached = true;
546                 }
547
548                 // name may be null
549                 return NameImpl;
550             }
551         }
552
553         public override bool HasDefaultValue
554         {
555             get
556             {
557                 if (m_noMetadata || m_noDefaultValue)
558                     return false;
559
560                 object defaultValue = GetDefaultValueInternal(false);
561
562                 return (defaultValue != DBNull.Value);
563             }
564         }
565
566         public override Object DefaultValue { get { return GetDefaultValue(false); } }
567         public override Object RawDefaultValue { get { return GetDefaultValue(true); } }
568
569         private Object GetDefaultValue(bool raw)
570         {
571             // OLD COMMENT (Is this even true?)
572             // Cannot cache because default value could be non-agile user defined enumeration.
573             // OLD COMMENT ends
574             if (m_noMetadata)
575                 return null;
576
577             // for dynamic method we pretend to have cached the value so we do not go to metadata
578             object defaultValue = GetDefaultValueInternal(raw);
579
580             if (defaultValue == DBNull.Value)
581             {
582                 #region Handle case if no default value was found
583 #if FEATURE_LEGACYNETCF
584                 if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8)
585                     defaultValue = null;
586                 else
587 #endif
588                 if (IsOptional)
589                 {
590                     // If the argument is marked as optional then the default value is Missing.Value.
591                     defaultValue = Type.Missing;
592                 }
593                 #endregion
594             }
595
596             return defaultValue;
597         }
598
599         // returns DBNull.Value if the parameter doesn't have a default value
600         [System.Security.SecuritySafeCritical]
601         private Object GetDefaultValueInternal(bool raw)
602         {
603             Contract.Assert(!m_noMetadata);
604
605             if (m_noDefaultValue)
606                 return DBNull.Value;
607
608             object defaultValue = null;
609
610             // Why check the parameter type only for DateTime and only for the ctor arguments? 
611             // No check on the parameter type is done for named args and for Decimal.
612
613             // We should move this after MdToken.IsNullToken(m_tkParamDef) and combine it 
614             // with the other custom attribute logic. But will that be a breaking change?
615             // For a DateTime parameter on which both an md constant and a ca constant are set,
616             // which one should win?
617             if (ParameterType == typeof(DateTime))
618             {
619                 if (raw)
620                 {
621                     CustomAttributeTypedArgument value =
622                         CustomAttributeData.Filter(
623                             CustomAttributeData.GetCustomAttributes(this), typeof(DateTimeConstantAttribute), 0);
624
625                     if (value.ArgumentType != null)
626                         return new DateTime((long)value.Value);
627                 }
628                 else
629                 {
630                     object[] dt = GetCustomAttributes(typeof(DateTimeConstantAttribute), false);
631                     if (dt != null && dt.Length != 0)
632                         return ((DateTimeConstantAttribute)dt[0]).Value;
633                 }
634             }
635
636             #region Look for a default value in metadata
637             if (!MdToken.IsNullToken(m_tkParamDef))
638             {
639                 // This will return DBNull.Value if no constant value is defined on m_tkParamDef in the metadata.
640                 defaultValue = MdConstant.GetValue(m_scope, m_tkParamDef, ParameterType.GetTypeHandleInternal(), raw);
641             }
642             #endregion
643
644             if (defaultValue == DBNull.Value)
645             {
646                 #region Look for a default value in the custom attributes
647                 if (raw)
648                 {
649                     foreach (CustomAttributeData attr in CustomAttributeData.GetCustomAttributes(this))
650                     {
651                         Type attrType = attr.Constructor.DeclaringType;
652
653                         if (attrType == typeof(DateTimeConstantAttribute))
654                         {
655                             defaultValue = DateTimeConstantAttribute.GetRawDateTimeConstant(attr);
656                         }
657                         else if (attrType == typeof(DecimalConstantAttribute))
658                         {
659                             defaultValue = DecimalConstantAttribute.GetRawDecimalConstant(attr);
660                         }
661                         else if (attrType.IsSubclassOf(s_CustomConstantAttributeType))
662                         {
663                             defaultValue = CustomConstantAttribute.GetRawConstant(attr);
664                         }
665                     }
666                 }
667                 else
668                 {
669                     Object[] CustomAttrs = GetCustomAttributes(s_CustomConstantAttributeType, false);
670                     if (CustomAttrs.Length != 0)
671                     {
672                         defaultValue = ((CustomConstantAttribute)CustomAttrs[0]).Value;
673                     }
674                     else
675                     {
676                         CustomAttrs = GetCustomAttributes(s_DecimalConstantAttributeType, false);
677                         if (CustomAttrs.Length != 0)
678                         {
679                             defaultValue = ((DecimalConstantAttribute)CustomAttrs[0]).Value;
680                         }
681                     }
682                 }
683                 #endregion
684             }
685
686             if (defaultValue == DBNull.Value)
687                 m_noDefaultValue = true;
688
689             return defaultValue;
690         }
691
692         internal RuntimeModule GetRuntimeModule()
693         {
694             RuntimeMethodInfo method = Member as RuntimeMethodInfo;
695             RuntimeConstructorInfo constructor = Member as RuntimeConstructorInfo;
696             RuntimePropertyInfo property = Member as RuntimePropertyInfo;
697
698             if (method != null)
699                 return method.GetRuntimeModule();
700             else if (constructor != null)
701                 return constructor.GetRuntimeModule();
702             else if (property != null)
703                 return property.GetRuntimeModule();
704             else
705                 return null;
706         }
707
708         public override int MetadataToken
709         {
710             get
711             {
712                 return m_tkParamDef; 
713             }
714         }
715
716         public override Type[] GetRequiredCustomModifiers()
717         {
718             return m_signature.GetCustomModifiers(PositionImpl + 1, true);
719         }
720
721         public override Type[] GetOptionalCustomModifiers()
722         {
723             return m_signature.GetCustomModifiers(PositionImpl + 1, false);
724         }
725
726         #endregion
727
728         #region ICustomAttributeProvider
729         public override Object[] GetCustomAttributes(bool inherit)
730         {
731             if (MdToken.IsNullToken(m_tkParamDef))
732                 return EmptyArray<Object>.Value;
733
734             return CustomAttribute.GetCustomAttributes(this, typeof(object) as RuntimeType);
735         }
736
737         public override Object[] GetCustomAttributes(Type attributeType, bool inherit)
738         {
739             if (attributeType == null)
740                 throw new ArgumentNullException("attributeType");
741             Contract.EndContractBlock();
742
743             if (MdToken.IsNullToken(m_tkParamDef))
744                 return EmptyArray<Object>.Value;
745
746             RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType;
747
748             if (attributeRuntimeType == null)
749                 throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "attributeType");
750
751             return CustomAttribute.GetCustomAttributes(this, attributeRuntimeType);
752         }
753
754         [System.Security.SecuritySafeCritical]  // auto-generated
755         public override bool IsDefined(Type attributeType, bool inherit)
756         {
757             if (attributeType == null)
758                 throw new ArgumentNullException("attributeType");
759             Contract.EndContractBlock();
760
761             if (MdToken.IsNullToken(m_tkParamDef))
762                 return false;
763
764             RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType;
765
766             if (attributeRuntimeType == null)
767                 throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "attributeType");
768
769             return CustomAttribute.IsDefined(this, attributeRuntimeType);
770         }
771
772         public override IList<CustomAttributeData> GetCustomAttributesData()
773         {
774             return CustomAttributeData.GetCustomAttributesInternal(this);
775         }
776         #endregion
777
778 #if FEATURE_REMOTING
779         #region Remoting Cache
780         private RemotingParameterCachedData m_cachedData;
781
782         internal RemotingParameterCachedData RemotingCache
783         {
784             get
785             {
786                 // This grabs an internal copy of m_cachedData and uses
787                 // that instead of looking at m_cachedData directly because
788                 // the cache may get cleared asynchronously.  This prevents
789                 // us from having to take a lock.
790                 RemotingParameterCachedData cache = m_cachedData;
791                 if (cache == null)
792                 {
793                     cache = new RemotingParameterCachedData(this);
794                     RemotingParameterCachedData ret = Interlocked.CompareExchange(ref m_cachedData, cache, null);
795                     if (ret != null)
796                         cache = ret;
797                 }
798                 return cache;
799             }
800         }
801         #endregion
802 #endif //FEATURE_REMOTING
803     }
804 }