1
0
mirror of https://github.com/JKorf/CryptoExchange.Net synced 2025-12-14 09:51:50 +00:00
This commit is contained in:
JKorf 2025-12-10 22:10:14 +01:00
parent ad1f5b843e
commit fe1e426da3
3 changed files with 73 additions and 20 deletions

View File

@ -2,6 +2,9 @@
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
#if NET8_0_OR_GREATER
using System.Collections.Frozen;
#endif
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
@ -64,7 +67,23 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
#endif #endif
: JsonConverter<T>, INullableConverterFactory where T : struct, Enum : JsonConverter<T>, INullableConverterFactory where T : struct, Enum
{ {
private static List<KeyValuePair<T, string>>? _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<EnumMapping>? _mapping = null;
#else
private static List<EnumMapping>? _mapping = null;
#endif
private NullableEnumConverter? _nullableEnumConverter = null; private NullableEnumConverter? _nullableEnumConverter = null;
private static ConcurrentBag<string> _unknownValuesWarned = new ConcurrentBag<string>(); private static ConcurrentBag<string> _unknownValuesWarned = new ConcurrentBag<string>();
@ -168,14 +187,27 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
{ {
if (_mapping != null) if (_mapping != null)
{ {
// Check for exact match first, then if not found fallback to a case insensitive match EnumMapping? mapping = null;
var mapping = _mapping.FirstOrDefault(kv => kv.Value.Equals(value, StringComparison.InvariantCulture)); // Try match on full equals
if (mapping.Equals(default(KeyValuePair<T, string>))) foreach (var item in _mapping)
mapping = _mapping.FirstOrDefault(kv => kv.Value.Equals(value, StringComparison.InvariantCultureIgnoreCase));
if (!mapping.Equals(default(KeyValuePair<T, string>)))
{ {
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; return true;
} }
} }
@ -215,9 +247,13 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
} }
} }
private static List<KeyValuePair<T, string>> AddMapping() #if NET8_0_OR_GREATER
private static FrozenSet<EnumMapping> AddMapping()
#else
private static List<EnumMapping> AddMapping()
#endif
{ {
var mapping = new List<KeyValuePair<T, string>>(); var mapping = new List<EnumMapping>();
var enumType = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T); var enumType = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T);
var enumMembers = enumType.GetFields(); var enumMembers = enumType.GetFields();
foreach (var member in enumMembers) foreach (var member in enumMembers)
@ -226,12 +262,15 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
foreach (MapAttribute attribute in maps) foreach (MapAttribute attribute in maps)
{ {
foreach (var value in attribute.Values) foreach (var value in attribute.Values)
mapping.Add(new KeyValuePair<T, string>((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; return mapping;
#endif
} }
/// <summary> /// <summary>
@ -245,7 +284,7 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
if (_mapping == null) if (_mapping == null)
_mapping = AddMapping(); _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());
} }
/// <summary> /// <summary>
@ -259,12 +298,26 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
if (_mapping == null) if (_mapping == null)
_mapping = AddMapping(); _mapping = AddMapping();
var mapping = _mapping.FirstOrDefault(kv => kv.Value.Equals(value, StringComparison.InvariantCulture)); EnumMapping? mapping = null;
if (mapping.Equals(default(KeyValuePair<T, string>))) // Try match on full equals
mapping = _mapping.FirstOrDefault(kv => kv.Value.Equals(value, StringComparison.InvariantCultureIgnoreCase)); foreach(var item in _mapping)
{
if (item.StringValue.Equals(value, StringComparison.Ordinal))
mapping = item;
}
if (!mapping.Equals(default(KeyValuePair<T, string>))) // If not found, try matching ignoring case
return mapping.Key; if (mapping == null)
{
foreach (var item in _mapping)
{
if (item.StringValue.Equals(value, StringComparison.OrdinalIgnoreCase))
mapping = item;
}
}
if (mapping != null)
return mapping.Value;
try try
{ {

View File

@ -52,7 +52,7 @@ namespace CryptoExchange.Net.Sockets
/// </summary> /// </summary>
public static MessageMatcher Create<T>(string value) public static MessageMatcher Create<T>(string value)
{ {
return new MessageMatcher(new MessageHandlerLink<T>(MessageLinkType.Full, value, (con, receiveTime, originalData, msg) => new CallResult<string>(default, null, null))); return new MessageMatcher(new MessageHandlerLink<T>(MessageLinkType.Full, value, (con, receiveTime, originalData, msg) => new CallResult<T>(default, null, null)));
} }
/// <summary> /// <summary>

View File

@ -29,7 +29,7 @@ namespace CryptoExchange.Net.Sockets
/// </summary> /// </summary>
public static MessageRouter CreateWithoutHandler<T>(string typeIdentifier) public static MessageRouter CreateWithoutHandler<T>(string typeIdentifier)
{ {
return new MessageRouter(new MessageRoute<T>(typeIdentifier, (string?)null, (con, receiveTime, originalData, msg) => new CallResult<string>(default, null, null))); return new MessageRouter(new MessageRoute<T>(typeIdentifier, (string?)null, (con, receiveTime, originalData, msg) => new CallResult<T>(default, null, null)));
} }
/// <summary> /// <summary>