diff --git a/CryptoExchange.Net/Converters/SystemTextJson/EnumConverter.cs b/CryptoExchange.Net/Converters/SystemTextJson/EnumConverter.cs index b4b02bd..d2f78e6 100644 --- a/CryptoExchange.Net/Converters/SystemTextJson/EnumConverter.cs +++ b/CryptoExchange.Net/Converters/SystemTextJson/EnumConverter.cs @@ -2,6 +2,9 @@ using Microsoft.Extensions.Logging; using System; using System.Collections.Concurrent; +#if NET8_0_OR_GREATER +using System.Collections.Frozen; +#endif using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; @@ -64,7 +67,23 @@ namespace CryptoExchange.Net.Converters.SystemTextJson #endif : JsonConverter, INullableConverterFactory where T : struct, Enum { - private static List>? _mapping = null; + class EnumMapping + { + public T Value { get; set; } + public string StringValue { get; set; } + + public EnumMapping(T value, string stringValue) + { + Value = value; + StringValue = stringValue; + } + } + +#if NET8_0_OR_GREATER + private static FrozenSet? _mapping = null; +#else + private static List? _mapping = null; +#endif private NullableEnumConverter? _nullableEnumConverter = null; private static ConcurrentBag _unknownValuesWarned = new ConcurrentBag(); @@ -168,14 +187,27 @@ namespace CryptoExchange.Net.Converters.SystemTextJson { if (_mapping != null) { - // Check for exact match first, then if not found fallback to a case insensitive match - var mapping = _mapping.FirstOrDefault(kv => kv.Value.Equals(value, StringComparison.InvariantCulture)); - if (mapping.Equals(default(KeyValuePair))) - mapping = _mapping.FirstOrDefault(kv => kv.Value.Equals(value, StringComparison.InvariantCultureIgnoreCase)); - - if (!mapping.Equals(default(KeyValuePair))) + EnumMapping? mapping = null; + // Try match on full equals + foreach (var item in _mapping) { - result = mapping.Key; + if (item.StringValue.Equals(value, StringComparison.Ordinal)) + mapping = item; + } + + // If not found, try matching ignoring case + if (mapping == null) + { + foreach (var item in _mapping) + { + if (item.StringValue.Equals(value, StringComparison.OrdinalIgnoreCase)) + mapping = item; + } + } + + if (mapping != null) + { + result = mapping.Value; return true; } } @@ -215,9 +247,13 @@ namespace CryptoExchange.Net.Converters.SystemTextJson } } - private static List> AddMapping() +#if NET8_0_OR_GREATER + private static FrozenSet AddMapping() +#else + private static List AddMapping() +#endif { - var mapping = new List>(); + var mapping = new List(); var enumType = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T); var enumMembers = enumType.GetFields(); foreach (var member in enumMembers) @@ -226,12 +262,15 @@ namespace CryptoExchange.Net.Converters.SystemTextJson foreach (MapAttribute attribute in maps) { foreach (var value in attribute.Values) - mapping.Add(new KeyValuePair((T)Enum.Parse(enumType, member.Name), value)); + mapping.Add(new EnumMapping((T)Enum.Parse(enumType, member.Name), value)); } } - _mapping = mapping; +#if NET8_0_OR_GREATER + return mapping.ToFrozenSet(); +#else return mapping; +#endif } /// @@ -245,7 +284,7 @@ namespace CryptoExchange.Net.Converters.SystemTextJson if (_mapping == null) _mapping = AddMapping(); - return enumValue == null ? null : (_mapping.FirstOrDefault(v => v.Key.Equals(enumValue)).Value ?? enumValue.ToString()); + return enumValue == null ? null : (_mapping.FirstOrDefault(v => v.Value.Equals(enumValue))?.StringValue ?? enumValue.ToString()); } /// @@ -259,12 +298,26 @@ namespace CryptoExchange.Net.Converters.SystemTextJson if (_mapping == null) _mapping = AddMapping(); - var mapping = _mapping.FirstOrDefault(kv => kv.Value.Equals(value, StringComparison.InvariantCulture)); - if (mapping.Equals(default(KeyValuePair))) - mapping = _mapping.FirstOrDefault(kv => kv.Value.Equals(value, StringComparison.InvariantCultureIgnoreCase)); + EnumMapping? mapping = null; + // Try match on full equals + foreach(var item in _mapping) + { + if (item.StringValue.Equals(value, StringComparison.Ordinal)) + mapping = item; + } - if (!mapping.Equals(default(KeyValuePair))) - return mapping.Key; + // If not found, try matching ignoring case + if (mapping == null) + { + foreach (var item in _mapping) + { + if (item.StringValue.Equals(value, StringComparison.OrdinalIgnoreCase)) + mapping = item; + } + } + + if (mapping != null) + return mapping.Value; try { diff --git a/CryptoExchange.Net/Sockets/MessageMatcher.cs b/CryptoExchange.Net/Sockets/MessageMatcher.cs index d081477..b208f44 100644 --- a/CryptoExchange.Net/Sockets/MessageMatcher.cs +++ b/CryptoExchange.Net/Sockets/MessageMatcher.cs @@ -52,7 +52,7 @@ namespace CryptoExchange.Net.Sockets /// public static MessageMatcher Create(string value) { - return new MessageMatcher(new MessageHandlerLink(MessageLinkType.Full, value, (con, receiveTime, originalData, msg) => new CallResult(default, null, null))); + return new MessageMatcher(new MessageHandlerLink(MessageLinkType.Full, value, (con, receiveTime, originalData, msg) => new CallResult(default, null, null))); } /// diff --git a/CryptoExchange.Net/Sockets/MessageRouter.cs b/CryptoExchange.Net/Sockets/MessageRouter.cs index e948cb2..0e44f76 100644 --- a/CryptoExchange.Net/Sockets/MessageRouter.cs +++ b/CryptoExchange.Net/Sockets/MessageRouter.cs @@ -29,7 +29,7 @@ namespace CryptoExchange.Net.Sockets /// public static MessageRouter CreateWithoutHandler(string typeIdentifier) { - return new MessageRouter(new MessageRoute(typeIdentifier, (string?)null, (con, receiveTime, originalData, msg) => new CallResult(default, null, null))); + return new MessageRouter(new MessageRoute(typeIdentifier, (string?)null, (con, receiveTime, originalData, msg) => new CallResult(default, null, null))); } ///