1
0
mirror of https://github.com/JKorf/CryptoExchange.Net synced 2025-06-08 16:36:15 +00:00

Add custom attribute cache. Resolves #82

This commit is contained in:
Matt Craig 2021-03-09 18:52:36 +08:00
parent 101fc8c1d8
commit 9f08fbb19d

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Concurrent;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
@ -14,6 +15,9 @@ namespace CryptoExchange.Net.Converters
/// </summary> /// </summary>
public class ArrayConverter : JsonConverter public class ArrayConverter : JsonConverter
{ {
private static readonly ConcurrentDictionary<(MemberInfo, Type), Attribute> attributeByMemberInfoAndTypeCache = new ConcurrentDictionary<(MemberInfo, Type), Attribute>();
private static readonly ConcurrentDictionary<(Type, Type), Attribute> attributeByTypeAndTypeCache = new ConcurrentDictionary<(Type, Type), Attribute>();
/// <inheritdoc /> /// <inheritdoc />
public override bool CanConvert(Type objectType) public override bool CanConvert(Type objectType)
{ {
@ -35,8 +39,8 @@ namespace CryptoExchange.Net.Converters
{ {
foreach (var property in objectType.GetProperties()) foreach (var property in objectType.GetProperties())
{ {
var attribute = var attribute = GetCustomAttribute<ArrayPropertyAttribute>(property);
(ArrayPropertyAttribute)property.GetCustomAttribute(typeof(ArrayPropertyAttribute));
if (attribute == null) if (attribute == null)
continue; continue;
@ -74,8 +78,9 @@ namespace CryptoExchange.Net.Converters
continue; continue;
} }
var converterAttribute = (JsonConverterAttribute)property.GetCustomAttribute(typeof(JsonConverterAttribute)) ?? (JsonConverterAttribute)property.PropertyType.GetCustomAttribute(typeof(JsonConverterAttribute)); var converterAttribute = GetCustomAttribute<JsonConverterAttribute>(property) ?? GetCustomAttribute<JsonConverterAttribute>(property.PropertyType);
var conversionAttribute = (JsonConversionAttribute)property.GetCustomAttribute(typeof(JsonConversionAttribute)) ?? (JsonConversionAttribute)property.PropertyType.GetCustomAttribute(typeof(JsonConversionAttribute)); var conversionAttribute = GetCustomAttribute<JsonConversionAttribute>(property) ?? GetCustomAttribute<JsonConversionAttribute>(property.PropertyType);
object? value; object? value;
if (converterAttribute != null) if (converterAttribute != null)
{ {
@ -122,12 +127,12 @@ namespace CryptoExchange.Net.Converters
writer.WriteStartArray(); writer.WriteStartArray();
var props = value.GetType().GetProperties(); var props = value.GetType().GetProperties();
var ordered = props.OrderBy(p => p.GetCustomAttribute<ArrayPropertyAttribute>()?.Index); var ordered = props.OrderBy(p => GetCustomAttribute<ArrayPropertyAttribute>(p)?.Index);
var last = -1; var last = -1;
foreach (var prop in ordered) foreach (var prop in ordered)
{ {
var arrayProp = prop.GetCustomAttribute<ArrayPropertyAttribute>(); var arrayProp = GetCustomAttribute<ArrayPropertyAttribute>(prop);
if (arrayProp == null) if (arrayProp == null)
continue; continue;
@ -141,7 +146,7 @@ namespace CryptoExchange.Net.Converters
} }
last = arrayProp.Index; last = arrayProp.Index;
var converterAttribute = (JsonConverterAttribute)prop.GetCustomAttribute(typeof(JsonConverterAttribute)); var converterAttribute = GetCustomAttribute<JsonConverterAttribute>(prop);
if (converterAttribute != null) if (converterAttribute != null)
writer.WriteRawValue(JsonConvert.SerializeObject(prop.GetValue(value), (JsonConverter)Activator.CreateInstance(converterAttribute.ConverterType))); writer.WriteRawValue(JsonConvert.SerializeObject(prop.GetValue(value), (JsonConverter)Activator.CreateInstance(converterAttribute.ConverterType)));
else if (!IsSimple(prop.PropertyType)) else if (!IsSimple(prop.PropertyType))
@ -164,6 +169,12 @@ namespace CryptoExchange.Net.Converters
|| type == typeof(string) || type == typeof(string)
|| type == typeof(decimal); || type == typeof(decimal);
} }
private static T? GetCustomAttribute<T>(MemberInfo memberInfo) where T : Attribute =>
(T?)attributeByMemberInfoAndTypeCache.GetOrAdd((memberInfo, typeof(T)), tuple => memberInfo.GetCustomAttribute(typeof(T)));
private static T? GetCustomAttribute<T>(Type type) where T : Attribute =>
(T?)attributeByTypeAndTypeCache.GetOrAdd((type, typeof(T)), tuple => type.GetCustomAttribute(typeof(T)));
} }
/// <summary> /// <summary>