Jon Skeet | 047575f | 2017-01-16 11:23:32 +0000 | [diff] [blame] | 1 | #region Copyright notice and license |
| 2 | // Protocol Buffers - Google's data interchange format |
| 3 | // Copyright 2017 Google Inc. All rights reserved. |
| 4 | // https://developers.google.com/protocol-buffers/ |
| 5 | // |
| 6 | // Redistribution and use in source and binary forms, with or without |
| 7 | // modification, are permitted provided that the following conditions are |
| 8 | // met: |
| 9 | // |
| 10 | // * Redistributions of source code must retain the above copyright |
| 11 | // notice, this list of conditions and the following disclaimer. |
| 12 | // * Redistributions in binary form must reproduce the above |
| 13 | // copyright notice, this list of conditions and the following disclaimer |
| 14 | // in the documentation and/or other materials provided with the |
| 15 | // distribution. |
| 16 | // * Neither the name of Google Inc. nor the names of its |
| 17 | // contributors may be used to endorse or promote products derived from |
| 18 | // this software without specific prior written permission. |
| 19 | // |
| 20 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 21 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 22 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 23 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 24 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 25 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 26 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 27 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 28 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 29 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 30 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 31 | #endregion |
| 32 | |
Sydney Acksman | 9e89b6e | 2019-05-03 15:54:41 -0500 | [diff] [blame] | 33 | using Google.Protobuf.Collections; |
Jon Skeet | 047575f | 2017-01-16 11:23:32 +0000 | [diff] [blame] | 34 | using System; |
Sydney Acksman | 9e89b6e | 2019-05-03 15:54:41 -0500 | [diff] [blame] | 35 | using System.Collections; |
Jon Skeet | 047575f | 2017-01-16 11:23:32 +0000 | [diff] [blame] | 36 | using System.Collections.Generic; |
James Newton-King | 22462b0 | 2021-11-03 10:50:09 +1300 | [diff] [blame] | 37 | using System.Diagnostics.CodeAnalysis; |
Sydney Acksman | 9e89b6e | 2019-05-03 15:54:41 -0500 | [diff] [blame] | 38 | using System.Linq; |
| 39 | using System.Reflection; |
Jon Skeet | 047575f | 2017-01-16 11:23:32 +0000 | [diff] [blame] | 40 | |
| 41 | namespace Google.Protobuf.Reflection |
| 42 | { |
| 43 | /// <summary> |
| 44 | /// Container for a set of custom options specified within a message, field etc. |
| 45 | /// </summary> |
| 46 | /// <remarks> |
| 47 | /// <para> |
| 48 | /// This type is publicly immutable, but internally mutable. It is only populated |
| 49 | /// by the descriptor parsing code - by the time any user code is able to see an instance, |
| 50 | /// it will be fully initialized. |
| 51 | /// </para> |
| 52 | /// <para> |
| 53 | /// If an option is requested using the incorrect method, an answer may still be returned: all |
| 54 | /// of the numeric types are represented internally using 64-bit integers, for example. It is up to |
| 55 | /// the caller to ensure that they make the appropriate method call for the option they're interested in. |
| 56 | /// Note that enum options are simply stored as integers, so the value should be fetched using |
| 57 | /// <see cref="TryGetInt32(int, out int)"/> and then cast appropriately. |
| 58 | /// </para> |
| 59 | /// <para> |
| 60 | /// Repeated options are currently not supported. Asking for a single value of an option |
| 61 | /// which was actually repeated will return the last value, except for message types where |
| 62 | /// all the set values are merged together. |
| 63 | /// </para> |
| 64 | /// </remarks> |
| 65 | public sealed class CustomOptions |
| 66 | { |
James Newton-King | 22462b0 | 2021-11-03 10:50:09 +1300 | [diff] [blame] | 67 | private const string UnreferencedCodeMessage = "CustomOptions is incompatible with trimming."; |
| 68 | |
Sydney Acksman | 9e89b6e | 2019-05-03 15:54:41 -0500 | [diff] [blame] | 69 | private static readonly object[] EmptyParameters = new object[0]; |
| 70 | private readonly IDictionary<int, IExtensionValue> values; |
Xiang Dai | e479410 | 2019-02-21 11:28:50 +0800 | [diff] [blame] | 71 | |
Sydney Acksman | 9e89b6e | 2019-05-03 15:54:41 -0500 | [diff] [blame] | 72 | internal CustomOptions(IDictionary<int, IExtensionValue> values) |
| 73 | { |
| 74 | this.values = values; |
| 75 | } |
Jon Skeet | 047575f | 2017-01-16 11:23:32 +0000 | [diff] [blame] | 76 | |
| 77 | /// <summary> |
| 78 | /// Retrieves a Boolean value for the specified option field. |
| 79 | /// </summary> |
| 80 | /// <param name="field">The field to fetch the value for.</param> |
| 81 | /// <param name="value">The output variable to populate.</param> |
| 82 | /// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns> |
James Newton-King | 22462b0 | 2021-11-03 10:50:09 +1300 | [diff] [blame] | 83 | [RequiresUnreferencedCode(UnreferencedCodeMessage)] |
Sydney Acksman | 9e89b6e | 2019-05-03 15:54:41 -0500 | [diff] [blame] | 84 | public bool TryGetBool(int field, out bool value) => TryGetPrimitiveValue(field, out value); |
Jon Skeet | 047575f | 2017-01-16 11:23:32 +0000 | [diff] [blame] | 85 | |
| 86 | /// <summary> |
| 87 | /// Retrieves a signed 32-bit integer value for the specified option field. |
| 88 | /// </summary> |
| 89 | /// <param name="field">The field to fetch the value for.</param> |
| 90 | /// <param name="value">The output variable to populate.</param> |
| 91 | /// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns> |
James Newton-King | 22462b0 | 2021-11-03 10:50:09 +1300 | [diff] [blame] | 92 | [RequiresUnreferencedCode(UnreferencedCodeMessage)] |
Sydney Acksman | 9e89b6e | 2019-05-03 15:54:41 -0500 | [diff] [blame] | 93 | public bool TryGetInt32(int field, out int value) => TryGetPrimitiveValue(field, out value); |
Jon Skeet | 047575f | 2017-01-16 11:23:32 +0000 | [diff] [blame] | 94 | |
| 95 | /// <summary> |
| 96 | /// Retrieves a signed 64-bit integer value for the specified option field. |
| 97 | /// </summary> |
| 98 | /// <param name="field">The field to fetch the value for.</param> |
| 99 | /// <param name="value">The output variable to populate.</param> |
| 100 | /// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns> |
James Newton-King | 22462b0 | 2021-11-03 10:50:09 +1300 | [diff] [blame] | 101 | [RequiresUnreferencedCode(UnreferencedCodeMessage)] |
Sydney Acksman | 9e89b6e | 2019-05-03 15:54:41 -0500 | [diff] [blame] | 102 | public bool TryGetInt64(int field, out long value) => TryGetPrimitiveValue(field, out value); |
Jon Skeet | 047575f | 2017-01-16 11:23:32 +0000 | [diff] [blame] | 103 | |
| 104 | /// <summary> |
| 105 | /// Retrieves an unsigned 32-bit integer value for the specified option field, |
| 106 | /// assuming a fixed-length representation. |
| 107 | /// </summary> |
| 108 | /// <param name="field">The field to fetch the value for.</param> |
| 109 | /// <param name="value">The output variable to populate.</param> |
| 110 | /// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns> |
James Newton-King | 22462b0 | 2021-11-03 10:50:09 +1300 | [diff] [blame] | 111 | [RequiresUnreferencedCode(UnreferencedCodeMessage)] |
Jon Skeet | 047575f | 2017-01-16 11:23:32 +0000 | [diff] [blame] | 112 | public bool TryGetFixed32(int field, out uint value) => TryGetUInt32(field, out value); |
| 113 | |
| 114 | /// <summary> |
| 115 | /// Retrieves an unsigned 64-bit integer value for the specified option field, |
| 116 | /// assuming a fixed-length representation. |
| 117 | /// </summary> |
| 118 | /// <param name="field">The field to fetch the value for.</param> |
| 119 | /// <param name="value">The output variable to populate.</param> |
| 120 | /// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns> |
James Newton-King | 22462b0 | 2021-11-03 10:50:09 +1300 | [diff] [blame] | 121 | [RequiresUnreferencedCode(UnreferencedCodeMessage)] |
Jon Skeet | 047575f | 2017-01-16 11:23:32 +0000 | [diff] [blame] | 122 | public bool TryGetFixed64(int field, out ulong value) => TryGetUInt64(field, out value); |
| 123 | |
| 124 | /// <summary> |
| 125 | /// Retrieves a signed 32-bit integer value for the specified option field, |
| 126 | /// assuming a fixed-length representation. |
| 127 | /// </summary> |
| 128 | /// <param name="field">The field to fetch the value for.</param> |
| 129 | /// <param name="value">The output variable to populate.</param> |
| 130 | /// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns> |
James Newton-King | 22462b0 | 2021-11-03 10:50:09 +1300 | [diff] [blame] | 131 | [RequiresUnreferencedCode(UnreferencedCodeMessage)] |
Jon Skeet | 047575f | 2017-01-16 11:23:32 +0000 | [diff] [blame] | 132 | public bool TryGetSFixed32(int field, out int value) => TryGetInt32(field, out value); |
| 133 | |
| 134 | /// <summary> |
| 135 | /// Retrieves a signed 64-bit integer value for the specified option field, |
| 136 | /// assuming a fixed-length representation. |
| 137 | /// </summary> |
| 138 | /// <param name="field">The field to fetch the value for.</param> |
| 139 | /// <param name="value">The output variable to populate.</param> |
| 140 | /// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns> |
James Newton-King | 22462b0 | 2021-11-03 10:50:09 +1300 | [diff] [blame] | 141 | [RequiresUnreferencedCode(UnreferencedCodeMessage)] |
Jon Skeet | 047575f | 2017-01-16 11:23:32 +0000 | [diff] [blame] | 142 | public bool TryGetSFixed64(int field, out long value) => TryGetInt64(field, out value); |
Xiang Dai | e479410 | 2019-02-21 11:28:50 +0800 | [diff] [blame] | 143 | |
Jon Skeet | 047575f | 2017-01-16 11:23:32 +0000 | [diff] [blame] | 144 | /// <summary> |
| 145 | /// Retrieves a signed 32-bit integer value for the specified option field, |
| 146 | /// assuming a zigzag encoding. |
| 147 | /// </summary> |
| 148 | /// <param name="field">The field to fetch the value for.</param> |
| 149 | /// <param name="value">The output variable to populate.</param> |
| 150 | /// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns> |
James Newton-King | 22462b0 | 2021-11-03 10:50:09 +1300 | [diff] [blame] | 151 | [RequiresUnreferencedCode(UnreferencedCodeMessage)] |
Sydney Acksman | 9e89b6e | 2019-05-03 15:54:41 -0500 | [diff] [blame] | 152 | public bool TryGetSInt32(int field, out int value) => TryGetPrimitiveValue(field, out value); |
Jon Skeet | 047575f | 2017-01-16 11:23:32 +0000 | [diff] [blame] | 153 | |
| 154 | /// <summary> |
| 155 | /// Retrieves a signed 64-bit integer value for the specified option field, |
| 156 | /// assuming a zigzag encoding. |
| 157 | /// </summary> |
| 158 | /// <param name="field">The field to fetch the value for.</param> |
| 159 | /// <param name="value">The output variable to populate.</param> |
| 160 | /// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns> |
James Newton-King | 22462b0 | 2021-11-03 10:50:09 +1300 | [diff] [blame] | 161 | [RequiresUnreferencedCode(UnreferencedCodeMessage)] |
Sydney Acksman | 9e89b6e | 2019-05-03 15:54:41 -0500 | [diff] [blame] | 162 | public bool TryGetSInt64(int field, out long value) => TryGetPrimitiveValue(field, out value); |
Jon Skeet | 047575f | 2017-01-16 11:23:32 +0000 | [diff] [blame] | 163 | |
| 164 | /// <summary> |
| 165 | /// Retrieves an unsigned 32-bit integer value for the specified option field. |
| 166 | /// </summary> |
| 167 | /// <param name="field">The field to fetch the value for.</param> |
| 168 | /// <param name="value">The output variable to populate.</param> |
| 169 | /// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns> |
James Newton-King | 22462b0 | 2021-11-03 10:50:09 +1300 | [diff] [blame] | 170 | [RequiresUnreferencedCode(UnreferencedCodeMessage)] |
Sydney Acksman | 9e89b6e | 2019-05-03 15:54:41 -0500 | [diff] [blame] | 171 | public bool TryGetUInt32(int field, out uint value) => TryGetPrimitiveValue(field, out value); |
Jon Skeet | 047575f | 2017-01-16 11:23:32 +0000 | [diff] [blame] | 172 | |
| 173 | /// <summary> |
| 174 | /// Retrieves an unsigned 64-bit integer value for the specified option field. |
| 175 | /// </summary> |
| 176 | /// <param name="field">The field to fetch the value for.</param> |
| 177 | /// <param name="value">The output variable to populate.</param> |
| 178 | /// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns> |
James Newton-King | 22462b0 | 2021-11-03 10:50:09 +1300 | [diff] [blame] | 179 | [RequiresUnreferencedCode(UnreferencedCodeMessage)] |
Sydney Acksman | 9e89b6e | 2019-05-03 15:54:41 -0500 | [diff] [blame] | 180 | public bool TryGetUInt64(int field, out ulong value) => TryGetPrimitiveValue(field, out value); |
Jon Skeet | 047575f | 2017-01-16 11:23:32 +0000 | [diff] [blame] | 181 | |
| 182 | /// <summary> |
| 183 | /// Retrieves a 32-bit floating point value for the specified option field. |
| 184 | /// </summary> |
| 185 | /// <param name="field">The field to fetch the value for.</param> |
| 186 | /// <param name="value">The output variable to populate.</param> |
| 187 | /// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns> |
James Newton-King | 22462b0 | 2021-11-03 10:50:09 +1300 | [diff] [blame] | 188 | [RequiresUnreferencedCode(UnreferencedCodeMessage)] |
Sydney Acksman | 9e89b6e | 2019-05-03 15:54:41 -0500 | [diff] [blame] | 189 | public bool TryGetFloat(int field, out float value) => TryGetPrimitiveValue(field, out value); |
Jon Skeet | 047575f | 2017-01-16 11:23:32 +0000 | [diff] [blame] | 190 | |
| 191 | /// <summary> |
| 192 | /// Retrieves a 64-bit floating point value for the specified option field. |
| 193 | /// </summary> |
| 194 | /// <param name="field">The field to fetch the value for.</param> |
| 195 | /// <param name="value">The output variable to populate.</param> |
| 196 | /// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns> |
James Newton-King | 22462b0 | 2021-11-03 10:50:09 +1300 | [diff] [blame] | 197 | [RequiresUnreferencedCode(UnreferencedCodeMessage)] |
Sydney Acksman | 9e89b6e | 2019-05-03 15:54:41 -0500 | [diff] [blame] | 198 | public bool TryGetDouble(int field, out double value) => TryGetPrimitiveValue(field, out value); |
Jon Skeet | 047575f | 2017-01-16 11:23:32 +0000 | [diff] [blame] | 199 | |
| 200 | /// <summary> |
| 201 | /// Retrieves a string value for the specified option field. |
| 202 | /// </summary> |
| 203 | /// <param name="field">The field to fetch the value for.</param> |
| 204 | /// <param name="value">The output variable to populate.</param> |
| 205 | /// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns> |
James Newton-King | 22462b0 | 2021-11-03 10:50:09 +1300 | [diff] [blame] | 206 | [RequiresUnreferencedCode(UnreferencedCodeMessage)] |
Sydney Acksman | 9e89b6e | 2019-05-03 15:54:41 -0500 | [diff] [blame] | 207 | public bool TryGetString(int field, out string value) => TryGetPrimitiveValue(field, out value); |
Jon Skeet | 047575f | 2017-01-16 11:23:32 +0000 | [diff] [blame] | 208 | |
| 209 | /// <summary> |
| 210 | /// Retrieves a bytes value for the specified option field. |
| 211 | /// </summary> |
| 212 | /// <param name="field">The field to fetch the value for.</param> |
| 213 | /// <param name="value">The output variable to populate.</param> |
| 214 | /// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns> |
James Newton-King | 22462b0 | 2021-11-03 10:50:09 +1300 | [diff] [blame] | 215 | [RequiresUnreferencedCode(UnreferencedCodeMessage)] |
Sydney Acksman | 9e89b6e | 2019-05-03 15:54:41 -0500 | [diff] [blame] | 216 | public bool TryGetBytes(int field, out ByteString value) => TryGetPrimitiveValue(field, out value); |
Jon Skeet | 047575f | 2017-01-16 11:23:32 +0000 | [diff] [blame] | 217 | |
| 218 | /// <summary> |
| 219 | /// Retrieves a message value for the specified option field. |
| 220 | /// </summary> |
| 221 | /// <param name="field">The field to fetch the value for.</param> |
| 222 | /// <param name="value">The output variable to populate.</param> |
| 223 | /// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns> |
James Newton-King | 22462b0 | 2021-11-03 10:50:09 +1300 | [diff] [blame] | 224 | [RequiresUnreferencedCode(UnreferencedCodeMessage)] |
Jon Skeet | 047575f | 2017-01-16 11:23:32 +0000 | [diff] [blame] | 225 | public bool TryGetMessage<T>(int field, out T value) where T : class, IMessage, new() |
| 226 | { |
Sydney Acksman | 9e89b6e | 2019-05-03 15:54:41 -0500 | [diff] [blame] | 227 | if (values == null) |
Jon Skeet | 047575f | 2017-01-16 11:23:32 +0000 | [diff] [blame] | 228 | { |
Sydney Acksman | 9e89b6e | 2019-05-03 15:54:41 -0500 | [diff] [blame] | 229 | value = default(T); |
Jon Skeet | 047575f | 2017-01-16 11:23:32 +0000 | [diff] [blame] | 230 | return false; |
| 231 | } |
Sydney Acksman | 9e89b6e | 2019-05-03 15:54:41 -0500 | [diff] [blame] | 232 | |
| 233 | IExtensionValue extensionValue; |
| 234 | if (values.TryGetValue(field, out extensionValue)) |
Jon Skeet | 047575f | 2017-01-16 11:23:32 +0000 | [diff] [blame] | 235 | { |
Sydney Acksman | 9e89b6e | 2019-05-03 15:54:41 -0500 | [diff] [blame] | 236 | if (extensionValue is ExtensionValue<T>) |
Jon Skeet | 047575f | 2017-01-16 11:23:32 +0000 | [diff] [blame] | 237 | { |
Sydney Acksman | 9e89b6e | 2019-05-03 15:54:41 -0500 | [diff] [blame] | 238 | ExtensionValue<T> single = extensionValue as ExtensionValue<T>; |
| 239 | ByteString bytes = single.GetValue().ToByteString(); |
| 240 | value = new T(); |
| 241 | value.MergeFrom(bytes); |
| 242 | return true; |
| 243 | } |
| 244 | else if (extensionValue is RepeatedExtensionValue<T>) |
| 245 | { |
| 246 | RepeatedExtensionValue<T> repeated = extensionValue as RepeatedExtensionValue<T>; |
| 247 | value = repeated.GetValue() |
| 248 | .Select(v => v.ToByteString()) |
| 249 | .Aggregate(new T(), (t, b) => |
| 250 | { |
| 251 | t.MergeFrom(b); |
| 252 | return t; |
| 253 | }); |
| 254 | return true; |
| 255 | } |
| 256 | } |
| 257 | |
| 258 | value = null; |
| 259 | return false; |
| 260 | } |
| 261 | |
James Newton-King | 22462b0 | 2021-11-03 10:50:09 +1300 | [diff] [blame] | 262 | [RequiresUnreferencedCode(UnreferencedCodeMessage)] |
Sydney Acksman | 9e89b6e | 2019-05-03 15:54:41 -0500 | [diff] [blame] | 263 | private bool TryGetPrimitiveValue<T>(int field, out T value) |
| 264 | { |
| 265 | if (values == null) |
| 266 | { |
| 267 | value = default(T); |
| 268 | return false; |
| 269 | } |
| 270 | |
| 271 | IExtensionValue extensionValue; |
| 272 | if (values.TryGetValue(field, out extensionValue)) |
| 273 | { |
| 274 | if (extensionValue is ExtensionValue<T>) |
| 275 | { |
| 276 | ExtensionValue<T> single = extensionValue as ExtensionValue<T>; |
Sydney Acksman | f4cfd2d | 2019-05-05 14:51:13 -0500 | [diff] [blame] | 277 | value = single.GetValue(); |
| 278 | return true; |
Jon Skeet | 047575f | 2017-01-16 11:23:32 +0000 | [diff] [blame] | 279 | } |
Sydney Acksman | 9e89b6e | 2019-05-03 15:54:41 -0500 | [diff] [blame] | 280 | else if (extensionValue is RepeatedExtensionValue<T>) |
Jon Skeet | 047575f | 2017-01-16 11:23:32 +0000 | [diff] [blame] | 281 | { |
Sydney Acksman | 9e89b6e | 2019-05-03 15:54:41 -0500 | [diff] [blame] | 282 | RepeatedExtensionValue<T> repeated = extensionValue as RepeatedExtensionValue<T>; |
| 283 | if (repeated.GetValue().Count != 0) |
| 284 | { |
| 285 | RepeatedField<T> repeatedField = repeated.GetValue(); |
| 286 | value = repeatedField[repeatedField.Count - 1]; |
| 287 | return true; |
| 288 | } |
Jon Skeet | 047575f | 2017-01-16 11:23:32 +0000 | [diff] [blame] | 289 | } |
Sydney Acksman | 9e89b6e | 2019-05-03 15:54:41 -0500 | [diff] [blame] | 290 | else // and here we find explicit enum handling since T : Enum ! x is ExtensionValue<Enum> |
Jon Skeet | 047575f | 2017-01-16 11:23:32 +0000 | [diff] [blame] | 291 | { |
Sydney Acksman | 9e89b6e | 2019-05-03 15:54:41 -0500 | [diff] [blame] | 292 | var type = extensionValue.GetType(); |
| 293 | if (type.GetGenericTypeDefinition() == typeof(ExtensionValue<>)) |
| 294 | { |
| 295 | var typeInfo = type.GetTypeInfo(); |
| 296 | var typeArgs = typeInfo.GenericTypeArguments; |
| 297 | if (typeArgs.Length == 1 && typeArgs[0].GetTypeInfo().IsEnum) |
| 298 | { |
Sydney Acksman | f4cfd2d | 2019-05-05 14:51:13 -0500 | [diff] [blame] | 299 | value = (T)typeInfo.GetDeclaredMethod(nameof(ExtensionValue<T>.GetValue)).Invoke(extensionValue, EmptyParameters); |
| 300 | return true; |
Sydney Acksman | 9e89b6e | 2019-05-03 15:54:41 -0500 | [diff] [blame] | 301 | } |
| 302 | } |
| 303 | else if (type.GetGenericTypeDefinition() == typeof(RepeatedExtensionValue<>)) |
| 304 | { |
| 305 | var typeInfo = type.GetTypeInfo(); |
| 306 | var typeArgs = typeInfo.GenericTypeArguments; |
| 307 | if (typeArgs.Length == 1 && typeArgs[0].GetTypeInfo().IsEnum) |
| 308 | { |
| 309 | var values = (IList)typeInfo.GetDeclaredMethod(nameof(RepeatedExtensionValue<T>.GetValue)).Invoke(extensionValue, EmptyParameters); |
| 310 | if (values.Count != 0) |
| 311 | { |
| 312 | value = (T)values[values.Count - 1]; |
| 313 | return true; |
| 314 | } |
| 315 | } |
| 316 | } |
Jon Skeet | 047575f | 2017-01-16 11:23:32 +0000 | [diff] [blame] | 317 | } |
| 318 | } |
Jon Skeet | 047575f | 2017-01-16 11:23:32 +0000 | [diff] [blame] | 319 | |
Sydney Acksman | 9e89b6e | 2019-05-03 15:54:41 -0500 | [diff] [blame] | 320 | value = default(T); |
| 321 | return false; |
Jon Skeet | 047575f | 2017-01-16 11:23:32 +0000 | [diff] [blame] | 322 | } |
| 323 | } |
| 324 | } |