summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/System/Reflection/RuntimePropertyInfo.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/mscorlib/src/System/Reflection/RuntimePropertyInfo.cs')
-rw-r--r--src/mscorlib/src/System/Reflection/RuntimePropertyInfo.cs467
1 files changed, 467 insertions, 0 deletions
diff --git a/src/mscorlib/src/System/Reflection/RuntimePropertyInfo.cs b/src/mscorlib/src/System/Reflection/RuntimePropertyInfo.cs
new file mode 100644
index 0000000000..b6a4792e4f
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/RuntimePropertyInfo.cs
@@ -0,0 +1,467 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.Contracts;
+using System.Globalization;
+using System.Runtime.Serialization;
+using System.Text;
+using RuntimeTypeCache = System.RuntimeType.RuntimeTypeCache;
+
+namespace System.Reflection
+{
+ [Serializable]
+ internal unsafe sealed class RuntimePropertyInfo : PropertyInfo, ISerializable
+ {
+ #region Private Data Members
+ private int m_token;
+ private string m_name;
+ private void* m_utf8name;
+ private PropertyAttributes m_flags;
+ private RuntimeTypeCache m_reflectedTypeCache;
+ private RuntimeMethodInfo m_getterMethod;
+ private RuntimeMethodInfo m_setterMethod;
+ private MethodInfo[] m_otherMethod;
+ private RuntimeType m_declaringType;
+ private BindingFlags m_bindingFlags;
+ private Signature m_signature;
+ private ParameterInfo[] m_parameters;
+ #endregion
+
+ #region Constructor
+ internal RuntimePropertyInfo(
+ int tkProperty, RuntimeType declaredType, RuntimeTypeCache reflectedTypeCache, out bool isPrivate)
+ {
+ Contract.Requires(declaredType != null);
+ Contract.Requires(reflectedTypeCache != null);
+ Debug.Assert(!reflectedTypeCache.IsGlobal);
+
+ MetadataImport scope = declaredType.GetRuntimeModule().MetadataImport;
+
+ m_token = tkProperty;
+ m_reflectedTypeCache = reflectedTypeCache;
+ m_declaringType = declaredType;
+
+ ConstArray sig;
+ scope.GetPropertyProps(tkProperty, out m_utf8name, out m_flags, out sig);
+
+ RuntimeMethodInfo dummy;
+ Associates.AssignAssociates(scope, tkProperty, declaredType, reflectedTypeCache.GetRuntimeType(),
+ out dummy, out dummy, out dummy,
+ out m_getterMethod, out m_setterMethod, out m_otherMethod,
+ out isPrivate, out m_bindingFlags);
+ }
+ #endregion
+
+ #region Internal Members
+ internal override bool CacheEquals(object o)
+ {
+ RuntimePropertyInfo m = o as RuntimePropertyInfo;
+
+ if ((object)m == null)
+ return false;
+
+ return m.m_token == m_token &&
+ RuntimeTypeHandle.GetModule(m_declaringType).Equals(
+ RuntimeTypeHandle.GetModule(m.m_declaringType));
+ }
+
+ internal Signature Signature
+ {
+ get
+ {
+ if (m_signature == null)
+ {
+ PropertyAttributes flags;
+ ConstArray sig;
+
+ void* name;
+ GetRuntimeModule().MetadataImport.GetPropertyProps(
+ m_token, out name, out flags, out sig);
+
+ m_signature = new Signature(sig.Signature.ToPointer(), (int)sig.Length, m_declaringType);
+ }
+
+ return m_signature;
+ }
+ }
+ internal bool EqualsSig(RuntimePropertyInfo target)
+ {
+ //@Asymmetry - Legacy policy is to remove duplicate properties, including hidden properties.
+ // The comparison is done by name and by sig. The EqualsSig comparison is expensive
+ // but forutnetly it is only called when an inherited property is hidden by name or
+ // when an interfaces declare properies with the same signature.
+ // Note that we intentionally don't resolve generic arguments so that we don't treat
+ // signatures that only match in certain instantiations as duplicates. This has the
+ // down side of treating overriding and overriden properties as different properties
+ // in some cases. But PopulateProperties in rttype.cs should have taken care of that
+ // by comparing VTable slots.
+ //
+ // Class C1(Of T, Y)
+ // Property Prop1(ByVal t1 As T) As Integer
+ // Get
+ // ... ...
+ // End Get
+ // End Property
+ // Property Prop1(ByVal y1 As Y) As Integer
+ // Get
+ // ... ...
+ // End Get
+ // End Property
+ // End Class
+ //
+
+ Contract.Requires(Name.Equals(target.Name));
+ Contract.Requires(this != target);
+ Contract.Requires(this.ReflectedType == target.ReflectedType);
+
+ return Signature.CompareSig(this.Signature, target.Signature);
+ }
+ internal BindingFlags BindingFlags { get { return m_bindingFlags; } }
+ #endregion
+
+ #region Object Overrides
+ public override String ToString()
+ {
+ return FormatNameAndSig(false);
+ }
+
+ private string FormatNameAndSig(bool serialization)
+ {
+ StringBuilder sbName = new StringBuilder(PropertyType.FormatTypeName(serialization));
+
+ sbName.Append(" ");
+ sbName.Append(Name);
+
+ RuntimeType[] arguments = Signature.Arguments;
+ if (arguments.Length > 0)
+ {
+ sbName.Append(" [");
+ sbName.Append(MethodBase.ConstructParameters(arguments, Signature.CallingConvention, serialization));
+ sbName.Append("]");
+ }
+
+ return sbName.ToString();
+ }
+ #endregion
+
+ #region ICustomAttributeProvider
+ public override Object[] GetCustomAttributes(bool inherit)
+ {
+ return CustomAttribute.GetCustomAttributes(this, typeof(object) as RuntimeType);
+ }
+
+ public override Object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ if (attributeType == null)
+ throw new ArgumentNullException(nameof(attributeType));
+ Contract.EndContractBlock();
+
+ RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType;
+
+ if (attributeRuntimeType == null)
+ throw new ArgumentException(SR.Arg_MustBeType, nameof(attributeType));
+
+ return CustomAttribute.GetCustomAttributes(this, attributeRuntimeType);
+ }
+
+ public override bool IsDefined(Type attributeType, bool inherit)
+ {
+ if (attributeType == null)
+ throw new ArgumentNullException(nameof(attributeType));
+ Contract.EndContractBlock();
+
+ RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType;
+
+ if (attributeRuntimeType == null)
+ throw new ArgumentException(SR.Arg_MustBeType, nameof(attributeType));
+
+ return CustomAttribute.IsDefined(this, attributeRuntimeType);
+ }
+
+ public override IList<CustomAttributeData> GetCustomAttributesData()
+ {
+ return CustomAttributeData.GetCustomAttributesInternal(this);
+ }
+ #endregion
+
+ #region MemberInfo Overrides
+ public override MemberTypes MemberType { get { return MemberTypes.Property; } }
+ public override String Name
+ {
+ get
+ {
+ if (m_name == null)
+ m_name = new Utf8String(m_utf8name).ToString();
+
+ return m_name;
+ }
+ }
+ public override Type DeclaringType
+ {
+ get
+ {
+ return m_declaringType;
+ }
+ }
+
+ public override Type ReflectedType
+ {
+ get
+ {
+ return ReflectedTypeInternal;
+ }
+ }
+
+ private RuntimeType ReflectedTypeInternal
+ {
+ get
+ {
+ return m_reflectedTypeCache.GetRuntimeType();
+ }
+ }
+
+ public override int MetadataToken { get { return m_token; } }
+
+ public override Module Module { get { return GetRuntimeModule(); } }
+ internal RuntimeModule GetRuntimeModule() { return m_declaringType.GetRuntimeModule(); }
+ #endregion
+
+ #region PropertyInfo Overrides
+
+ #region Non Dynamic
+
+ public override Type[] GetRequiredCustomModifiers()
+ {
+ return Signature.GetCustomModifiers(0, true);
+ }
+
+ public override Type[] GetOptionalCustomModifiers()
+ {
+ return Signature.GetCustomModifiers(0, false);
+ }
+
+ internal object GetConstantValue(bool raw)
+ {
+ Object defaultValue = MdConstant.GetValue(GetRuntimeModule().MetadataImport, m_token, PropertyType.GetTypeHandleInternal(), raw);
+
+ if (defaultValue == DBNull.Value)
+ // Arg_EnumLitValueNotFound -> "Literal value was not found."
+ throw new InvalidOperationException(SR.Arg_EnumLitValueNotFound);
+
+ return defaultValue;
+ }
+
+ public override object GetConstantValue() { return GetConstantValue(false); }
+
+ public override object GetRawConstantValue() { return GetConstantValue(true); }
+
+ public override MethodInfo[] GetAccessors(bool nonPublic)
+ {
+ List<MethodInfo> accessorList = new List<MethodInfo>();
+
+ if (Associates.IncludeAccessor(m_getterMethod, nonPublic))
+ accessorList.Add(m_getterMethod);
+
+ if (Associates.IncludeAccessor(m_setterMethod, nonPublic))
+ accessorList.Add(m_setterMethod);
+
+ if ((object)m_otherMethod != null)
+ {
+ for (int i = 0; i < m_otherMethod.Length; i++)
+ {
+ if (Associates.IncludeAccessor(m_otherMethod[i] as MethodInfo, nonPublic))
+ accessorList.Add(m_otherMethod[i]);
+ }
+ }
+ return accessorList.ToArray();
+ }
+
+ public override Type PropertyType
+ {
+ get { return Signature.ReturnType; }
+ }
+
+ public override MethodInfo GetGetMethod(bool nonPublic)
+ {
+ if (!Associates.IncludeAccessor(m_getterMethod, nonPublic))
+ return null;
+
+ return m_getterMethod;
+ }
+
+ public override MethodInfo GetSetMethod(bool nonPublic)
+ {
+ if (!Associates.IncludeAccessor(m_setterMethod, nonPublic))
+ return null;
+
+ return m_setterMethod;
+ }
+
+ public override ParameterInfo[] GetIndexParameters()
+ {
+ ParameterInfo[] indexParams = GetIndexParametersNoCopy();
+
+ int numParams = indexParams.Length;
+
+ if (numParams == 0)
+ return indexParams;
+
+ ParameterInfo[] ret = new ParameterInfo[numParams];
+
+ Array.Copy(indexParams, ret, numParams);
+
+ return ret;
+ }
+
+ internal ParameterInfo[] GetIndexParametersNoCopy()
+ {
+ // @History - Logic ported from RTM
+
+ // No need to lock because we don't guarantee the uniqueness of ParameterInfo objects
+ if (m_parameters == null)
+ {
+ int numParams = 0;
+ ParameterInfo[] methParams = null;
+
+ // First try to get the Get method.
+ MethodInfo m = GetGetMethod(true);
+ if (m != null)
+ {
+ // There is a Get method so use it.
+ methParams = m.GetParametersNoCopy();
+ numParams = methParams.Length;
+ }
+ else
+ {
+ // If there is no Get method then use the Set method.
+ m = GetSetMethod(true);
+
+ if (m != null)
+ {
+ methParams = m.GetParametersNoCopy();
+ numParams = methParams.Length - 1;
+ }
+ }
+
+ // Now copy over the parameter info's and change their
+ // owning member info to the current property info.
+
+ ParameterInfo[] propParams = new ParameterInfo[numParams];
+
+ for (int i = 0; i < numParams; i++)
+ propParams[i] = new RuntimeParameterInfo((RuntimeParameterInfo)methParams[i], this);
+
+ m_parameters = propParams;
+ }
+
+ return m_parameters;
+ }
+
+ public override PropertyAttributes Attributes
+ {
+ get
+ {
+ return m_flags;
+ }
+ }
+
+ public override bool CanRead
+ {
+ get
+ {
+ return m_getterMethod != null;
+ }
+ }
+
+ public override bool CanWrite
+ {
+ get
+ {
+ return m_setterMethod != null;
+ }
+ }
+ #endregion
+
+ #region Dynamic
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ public override Object GetValue(Object obj, Object[] index)
+ {
+ return GetValue(obj, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static,
+ null, index, null);
+ }
+
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ public override Object GetValue(Object obj, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
+ {
+ MethodInfo m = GetGetMethod(true);
+ if (m == null)
+ throw new ArgumentException(System.SR.Arg_GetMethNotFnd);
+ return m.Invoke(obj, invokeAttr, binder, index, null);
+ }
+
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ public override void SetValue(Object obj, Object value, Object[] index)
+ {
+ SetValue(obj,
+ value,
+ BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static,
+ null,
+ index,
+ null);
+ }
+
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ public override void SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
+ {
+ MethodInfo m = GetSetMethod(true);
+
+ if (m == null)
+ throw new ArgumentException(System.SR.Arg_SetMethNotFnd);
+
+ Object[] args = null;
+
+ if (index != null)
+ {
+ args = new Object[index.Length + 1];
+
+ for (int i = 0; i < index.Length; i++)
+ args[i] = index[i];
+
+ args[index.Length] = value;
+ }
+ else
+ {
+ args = new Object[1];
+ args[0] = value;
+ }
+
+ m.Invoke(obj, invokeAttr, binder, args, culture);
+ }
+ #endregion
+
+ #endregion
+
+ #region ISerializable Implementation
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null)
+ throw new ArgumentNullException(nameof(info));
+ Contract.EndContractBlock();
+
+ MemberInfoSerializationHolder.GetSerializationInfo(info, this);
+ }
+
+ internal string SerializationToString()
+ {
+ return FormatNameAndSig(true);
+ }
+ #endregion
+ }
+}