< Summary

Line coverage
0%
Covered lines: 0
Uncovered lines: 74
Coverable lines: 74
Total lines: 195
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 37
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor(...)100%110%
DecodeValue(...)100%110%
GetProjectedValue()0%220%
GetProjectedValue(...)0%11110%
ProjectAttributeTargetValue(...)0%22220%

File(s)

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeSystem/CustomAttribute.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System.Diagnostics;
 5using System.Reflection.Metadata.Ecma335;
 6
 7namespace System.Reflection.Metadata
 8{
 9    public readonly struct CustomAttribute
 10    {
 11        private readonly MetadataReader _reader;
 12
 13        // Workaround: JIT doesn't generate good code for nested structures, so use RowId.
 14        private readonly uint _treatmentAndRowId;
 15
 16        internal CustomAttribute(MetadataReader reader, uint treatmentAndRowId)
 017        {
 018            _reader = reader;
 019            _treatmentAndRowId = treatmentAndRowId;
 020        }
 21
 22        private int RowId
 23        {
 024            get { return (int)(_treatmentAndRowId & TokenTypeIds.RIDMask); }
 25        }
 26
 27        private CustomAttributeHandle Handle
 28        {
 029            get { return CustomAttributeHandle.FromRowId(RowId); }
 30        }
 31
 32        private MethodDefTreatment Treatment
 33        {
 034            get { return (MethodDefTreatment)(_treatmentAndRowId >> TokenTypeIds.RowIdBitCount); }
 35        }
 36
 37        /// <summary>
 38        /// The constructor (<see cref="MethodDefinitionHandle"/> or <see cref="MemberReferenceHandle"/>) of the custom 
 39        /// </summary>
 40        /// <remarks>
 41        /// Corresponds to Type field of CustomAttribute table in ECMA-335 Standard.
 42        /// </remarks>
 43        public EntityHandle Constructor
 44        {
 45            get
 046            {
 047                return _reader.CustomAttributeTable.GetConstructor(Handle);
 048            }
 49        }
 50
 51        /// <summary>
 52        /// The handle of the metadata entity the attribute is applied to.
 53        /// </summary>
 54        /// <remarks>
 55        /// Corresponds to Parent field of CustomAttribute table in ECMA-335 Standard.
 56        /// </remarks>
 57        public EntityHandle Parent
 58        {
 59            get
 060            {
 061                return _reader.CustomAttributeTable.GetParent(Handle);
 062            }
 63        }
 64
 65        /// <summary>
 66        /// The value of the attribute.
 67        /// </summary>
 68        /// <remarks>
 69        /// Corresponds to Value field of CustomAttribute table in ECMA-335 Standard.
 70        /// </remarks>
 71        public BlobHandle Value
 72        {
 73            get
 074            {
 075                if (Treatment == 0)
 076                {
 077                    return _reader.CustomAttributeTable.GetValue(Handle);
 78                }
 79
 080                return GetProjectedValue();
 081            }
 82        }
 83
 84        /// <summary>
 85        /// Decodes the arguments encoded in the value blob.
 86        /// </summary>
 87        public CustomAttributeValue<TType> DecodeValue<TType>(ICustomAttributeTypeProvider<TType> provider)
 088        {
 089            var decoder = new CustomAttributeDecoder<TType>(provider, _reader);
 090            return decoder.DecodeValue(Constructor, Value);
 091        }
 92
 93        #region Projections
 94
 95        private BlobHandle GetProjectedValue()
 096        {
 97            // The usual pattern for accessing custom attributes differs from pattern for accessing e.g. TypeDef row fie
 98            // The value blob is only accessed when the consumer is about to decode it (which is a nontrivial process),
 99            // while the Constructor and Parent fields are often accessed when searching for a particular attribute.
 100            //
 101            // The current WinMD projections only affect the blob and not the Constructor and Parent values.
 102            // It is thus more efficient to calculate the treatment here (and make GetValue more expensive) and
 103            // avoid calculating the treatment when the CustomAttributeHandle is looked up and CustomAttribute struct
 104            // is initialized.
 105
 0106            CustomAttributeValueTreatment treatment = _reader.CalculateCustomAttributeValueTreatment(Handle);
 0107            if (treatment == 0)
 0108            {
 0109                return _reader.CustomAttributeTable.GetValue(Handle);
 110            }
 111
 0112            return GetProjectedValue(treatment);
 0113        }
 114
 115        private BlobHandle GetProjectedValue(CustomAttributeValueTreatment treatment)
 0116        {
 117            BlobHandle.VirtualIndex virtualIndex;
 118            bool isVersionOrDeprecated;
 0119            switch (treatment)
 120            {
 121                case CustomAttributeValueTreatment.AttributeUsageVersionAttribute:
 122                case CustomAttributeValueTreatment.AttributeUsageDeprecatedAttribute:
 0123                    virtualIndex = BlobHandle.VirtualIndex.AttributeUsage_AllowMultiple;
 0124                    isVersionOrDeprecated = true;
 0125                    break;
 126
 127                case CustomAttributeValueTreatment.AttributeUsageAllowMultiple:
 0128                    virtualIndex = BlobHandle.VirtualIndex.AttributeUsage_AllowMultiple;
 0129                    isVersionOrDeprecated = false;
 0130                    break;
 131
 132                case CustomAttributeValueTreatment.AttributeUsageAllowSingle:
 0133                    virtualIndex = BlobHandle.VirtualIndex.AttributeUsage_AllowSingle;
 0134                    isVersionOrDeprecated = false;
 0135                    break;
 136
 137                default:
 0138                    Debug.Fail($"Unexpected treatment {treatment}");
 139                    return default(BlobHandle);
 140            }
 141
 142            // Raw blob format:
 143            //    01 00        - Fixed prolog for CA's
 144            //    xx xx xx xx  - The Windows.Foundation.Metadata.AttributeTarget value
 145            //    00 00        - Indicates 0 name/value pairs following.
 0146            var rawBlob = _reader.CustomAttributeTable.GetValue(Handle);
 0147            var rawBlobReader = _reader.GetBlobReader(rawBlob);
 0148            if (rawBlobReader.Length != 8)
 0149            {
 0150                return rawBlob;
 151            }
 152
 0153            if (rawBlobReader.ReadInt16() != 1)
 0154            {
 0155                return rawBlob;
 156            }
 157
 0158            AttributeTargets projectedValue = ProjectAttributeTargetValue(rawBlobReader.ReadUInt32());
 0159            if (isVersionOrDeprecated)
 0160            {
 0161                projectedValue |= AttributeTargets.Constructor | AttributeTargets.Property;
 0162            }
 163
 0164            return BlobHandle.FromVirtualIndex(virtualIndex, (ushort)projectedValue);
 0165        }
 166
 167        private static AttributeTargets ProjectAttributeTargetValue(uint rawValue)
 0168        {
 169            // Windows.Foundation.Metadata.AttributeTargets.All
 0170            if (rawValue == 0xffffffff)
 0171            {
 0172                return AttributeTargets.All;
 173            }
 174
 0175            AttributeTargets result = 0;
 176
 0177            if ((rawValue & 0x00000001) != 0) result |= AttributeTargets.Delegate;
 0178            if ((rawValue & 0x00000002) != 0) result |= AttributeTargets.Enum;
 0179            if ((rawValue & 0x00000004) != 0) result |= AttributeTargets.Event;
 0180            if ((rawValue & 0x00000008) != 0) result |= AttributeTargets.Field;
 0181            if ((rawValue & 0x00000010) != 0) result |= AttributeTargets.Interface;
 182            // InterfaceGroup (no equivalent in CLR)
 0183            if ((rawValue & 0x00000040) != 0) result |= AttributeTargets.Method;
 0184            if ((rawValue & 0x00000080) != 0) result |= AttributeTargets.Parameter;
 0185            if ((rawValue & 0x00000100) != 0) result |= AttributeTargets.Property;
 0186            if ((rawValue & 0x00000200) != 0) result |= AttributeTargets.Class;
 0187            if ((rawValue & 0x00000400) != 0) result |= AttributeTargets.Struct;
 188            // InterfaceImpl (no equivalent in CLR)
 189
 0190            return result;
 0191        }
 192        #endregion
 193    }
 194}
 195