File: System\Reflection\Runtime\PropertyInfos\NativeFormat\NativeFormatRuntimePropertyInfo.cs
Web Access
Project: src\src\runtime\src\coreclr\nativeaot\System.Private.CoreLib\src\System.Private.CoreLib.csproj (System.Private.CoreLib)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Reflection.Runtime.CustomAttributes;
using System.Reflection.Runtime.General;
using System.Reflection.Runtime.General.NativeFormat;
using System.Reflection.Runtime.MethodInfos;
using System.Reflection.Runtime.MethodInfos.NativeFormat;
using System.Reflection.Runtime.ParameterInfos;
using System.Reflection.Runtime.TypeInfos;
using System.Reflection.Runtime.TypeInfos.NativeFormat;
using System.Runtime.CompilerServices;
using System.Text;

using Internal.Metadata.NativeFormat;
using Internal.Reflection.Core;
using Internal.Reflection.Core.Execution;

using NativeFormatMethodSemanticsAttributes = global::Internal.Metadata.NativeFormat.MethodSemanticsAttributes;

namespace System.Reflection.Runtime.PropertyInfos.NativeFormat
{
    //
    // The runtime's implementation of PropertyInfo's
    //
    [DebuggerDisplay("{_debugName}")]
    internal sealed partial class NativeFormatRuntimePropertyInfo : RuntimePropertyInfo
    {
        //
        // propertyHandle - the "tkPropertyDef" that identifies the property.
        // definingType   - the "tkTypeDef" that defined the field (this is where you get the metadata reader that created propertyHandle.)
        // contextType    - the type that supplies the type context (i.e. substitutions for generic parameters.) Though you
        //                  get your raw information from "definingType", you report "contextType" as your DeclaringType property.
        //
        //  For example:
        //
        //       typeof(Foo<>).GetTypeInfo().DeclaredMembers
        //
        //           The definingType and contextType are both Foo<>
        //
        //       typeof(Foo<int,String>).GetTypeInfo().DeclaredMembers
        //
        //          The definingType is "Foo<,>"
        //          The contextType is "Foo<int,String>"
        //
        //  We don't report any DeclaredMembers for arrays or generic parameters so those don't apply.
        //
        private NativeFormatRuntimePropertyInfo(PropertyHandle propertyHandle, NativeFormatRuntimeNamedTypeInfo definingTypeInfo, RuntimeTypeInfo contextTypeInfo, RuntimeTypeInfo reflectedType) :
            base(contextTypeInfo, reflectedType)
        {
            _propertyHandle = propertyHandle;
            _definingTypeInfo = definingTypeInfo;
            _reader = definingTypeInfo.Reader;
            _property = propertyHandle.GetProperty(_reader);
        }

        public sealed override PropertyAttributes Attributes
        {
            get
            {
                return _property.Flags;
            }
        }

        public sealed override IEnumerable<CustomAttributeData> CustomAttributes
        {
            get
            {
                return RuntimeCustomAttributeData.GetCustomAttributes(_reader, _property.CustomAttributes);
            }
        }

        public override Type GetModifiedPropertyType()
        {
            return ModifiedType.Create(PropertyType, _reader, _reader.GetPropertySignature(_property.Signature).Type);

        }

        public sealed override bool HasSameMetadataDefinitionAs(MemberInfo other)
        {
            ArgumentNullException.ThrowIfNull(other);

            if (!(other is NativeFormatRuntimePropertyInfo otherProperty))
                return false;
            if (!(_reader == otherProperty._reader))
                return false;
            if (!(_propertyHandle.Equals(otherProperty._propertyHandle)))
                return false;
            if (!(_definingTypeInfo.Equals(otherProperty._definingTypeInfo)))
                return false;
            return true;
        }

        public sealed override bool Equals(object obj)
        {
            if (!(obj is NativeFormatRuntimePropertyInfo other))
                return false;
            if (!(_reader == other._reader))
                return false;
            if (!(_propertyHandle.Equals(other._propertyHandle)))
                return false;
            if (!(ContextTypeInfo.Equals(other.ContextTypeInfo)))
                return false;
            if (!(_reflectedType.Equals(other._reflectedType)))
                return false;
            return true;
        }

        public sealed override int GetHashCode()
        {
            return HashCode.Combine(_propertyHandle, ContextTypeInfo, _reflectedType);
        }

        public sealed override int MetadataToken
        {
            get
            {
                throw new InvalidOperationException(SR.NoMetadataTokenAvailable);
            }
        }

        protected sealed override QSignatureTypeHandle PropertyTypeHandle
        {
            get
            {
                return new QSignatureTypeHandle(_reader, _property.Signature.GetPropertySignature(_reader).Type);
            }
        }

        protected sealed override bool GetDefaultValueIfAny(bool raw, out object? defaultValue)
        {
            return DefaultValueParser.GetDefaultValueFromConstantIfAny(_reader, _property.DefaultValue, PropertyType, raw, out defaultValue)
                || DefaultValueParser.GetDefaultValueFromAttributeIfAny(CustomAttributes, raw, out defaultValue);
        }

        protected sealed override RuntimeNamedMethodInfo GetPropertyMethod(PropertyMethodSemantics whichMethod)
        {
            NativeFormatMethodSemanticsAttributes localMethodSemantics;
            switch (whichMethod)
            {
                case PropertyMethodSemantics.Getter:
                    localMethodSemantics = NativeFormatMethodSemanticsAttributes.Getter;
                    break;

                case PropertyMethodSemantics.Setter:
                    localMethodSemantics = NativeFormatMethodSemanticsAttributes.Setter;
                    break;

                default:
                    return null;
            }

            bool inherited = !_reflectedType.Equals(ContextTypeInfo);

            foreach (MethodSemanticsHandle methodSemanticsHandle in _property.MethodSemantics)
            {
                MethodSemantics methodSemantics = methodSemanticsHandle.GetMethodSemantics(_reader);
                if (methodSemantics.Attributes == localMethodSemantics)
                {
                    MethodHandle methodHandle = methodSemantics.Method;

                    if (inherited)
                    {
                        MethodAttributes flags = methodHandle.GetMethod(_reader).Flags;
                        if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private)
                            continue;
                    }

                    return RuntimeNamedMethodInfo<NativeFormatMethodCommon>.GetRuntimeNamedMethodInfo(new NativeFormatMethodCommon(methodHandle, _definingTypeInfo, ContextTypeInfo), _reflectedType);
                }
            }

            return null;
        }

        protected sealed override string MetadataName
        {
            get
            {
                return _property.Name.GetString(_reader);
            }
        }

        protected sealed override RuntimeTypeInfo DefiningTypeInfo
        {
            get
            {
                return _definingTypeInfo;
            }
        }

        private readonly NativeFormatRuntimeNamedTypeInfo _definingTypeInfo;
        private readonly PropertyHandle _propertyHandle;

        private readonly MetadataReader _reader;
        private readonly Property _property;
    }
}