Welcome to mirror list, hosted at ThFree Co, Russian Federation.

DefaultValueProcessing.cs « EcmaFormat « General « Runtime « Reflection « System « src « System.Private.Reflection.Core « src - github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 70b02039324255f3811682c0268b43107ddc1b1f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// 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;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Reflection.Runtime.General;

using Internal.Reflection.Extensions.NonPortable;

using System.Reflection.Metadata;

namespace System.Reflection.Runtime.General.EcmaFormat
{
    internal static class DefaultValueProcessing
    {
        public static bool GetDefaultValueIfAny(MetadataReader reader, ref FieldDefinition field, FieldInfo fieldInfo, bool raw, out object defaultValue)
        {
            if (0 != (field.Attributes & FieldAttributes.HasDefault))
            {
                defaultValue = ConstantValueAsObject(field.GetDefaultValue(), reader, fieldInfo.FieldType, raw);
                return true;
            }
            else
            {
                return Helpers.GetCustomAttributeDefaultValueIfAny(fieldInfo.CustomAttributes, raw, out defaultValue);
            }
        }

        public static bool GetDefaultValueIfAny(MetadataReader reader, ref Parameter parameter, ParameterInfo parameterInfo, bool raw, out object defaultValue)
        {
            if (0 != (parameter.Attributes & ParameterAttributes.HasDefault))
            {
                defaultValue = ConstantValueAsObject(parameter.GetDefaultValue(), reader, parameterInfo.ParameterType, raw);
                return true;
            }
            else
            {
                return Helpers.GetCustomAttributeDefaultValueIfAny(parameterInfo.CustomAttributes, raw, out defaultValue);
            }
        }

        public static bool GetDefaultValueIfAny(MetadataReader reader, ref PropertyDefinition property, PropertyInfo propertyInfo, bool raw, out object defaultValue)
        {
            if (0 != (property.Attributes & PropertyAttributes.HasDefault))
            {
                defaultValue = ConstantValueAsObject(property.GetDefaultValue(), reader, propertyInfo.PropertyType, raw);
                return true;
            }
            else
            {
                // Custom attributes default values cannot be specified on properties
                defaultValue = null;
                return false;
            }
        }

        private static object ConstantValueAsObject(ConstantHandle constantHandle, MetadataReader metadataReader, Type declaredType, bool raw)
        {
            object defaultValue = ConstantValueAsRawObject(constantHandle, metadataReader);
            if ((!raw) && declaredType.IsEnum && defaultValue != null)
                defaultValue = Enum.ToObject(declaredType, defaultValue);
            return defaultValue;
        }


        private static object ConstantValueAsRawObject(ConstantHandle constantHandle, MetadataReader metadataReader)
        {
            if (constantHandle.IsNil)
                throw new BadImageFormatException();

            Constant constantValue = metadataReader.GetConstant(constantHandle);

            if (constantValue.Value.IsNil)
                throw new BadImageFormatException();

            BlobReader reader = metadataReader.GetBlobReader(constantValue.Value);

            switch (constantValue.TypeCode)
            {
                case ConstantTypeCode.Boolean:
                    return reader.ReadBoolean();

                case ConstantTypeCode.Char:
                    return reader.ReadChar();

                case ConstantTypeCode.SByte:
                    return reader.ReadSByte();

                case ConstantTypeCode.Int16:
                    return reader.ReadInt16();

                case ConstantTypeCode.Int32:
                    return reader.ReadInt32();

                case ConstantTypeCode.Int64:
                    return reader.ReadInt64();

                case ConstantTypeCode.Byte:
                    return reader.ReadByte();

                case ConstantTypeCode.UInt16:
                    return reader.ReadUInt16();

                case ConstantTypeCode.UInt32:
                    return reader.ReadUInt32();

                case ConstantTypeCode.UInt64:
                    return reader.ReadUInt64();

                case ConstantTypeCode.Single:
                    return reader.ReadSingle();

                case ConstantTypeCode.Double:
                    return reader.ReadDouble();

                case ConstantTypeCode.String:
                    return reader.ReadUTF16(reader.Length);

                case ConstantTypeCode.NullReference:
                    // Partition II section 22.9:
                    // The encoding of Type for the nullref value is ELEMENT_TYPE_CLASS with a Value of a 4-byte zero.
                    // Unlike uses of ELEMENT_TYPE_CLASS in signatures, this one is not followed by a type token.
                    if (reader.ReadUInt32() == 0)
                    {
                        return null;
                    }

                    break;
            }

            throw new BadImageFormatException();
        } 
    }
}