<PackageReference Include="NJsonSchema" Version="9.1.10" />

ReflectionCache

public static class ReflectionCache
using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; namespace NJsonSchema.Infrastructure { public static class ReflectionCache { public class PropertyOrField { public MemberInfo MemberInfo { get; } public CustomAttributes CustomAttributes { get; } public bool CanRead => (MemberInfo as PropertyInfo)?.CanRead ?? true; public bool IsIndexer { get { if (MemberInfo is PropertyInfo) return ((PropertyInfo)MemberInfo).GetIndexParameters().Length != 0; return false; } } public PropertyOrField(MemberInfo memberInfo, CustomAttributes customAttributes) { MemberInfo = memberInfo; CustomAttributes = customAttributes; } public object GetValue(object obj) { if (MemberInfo is PropertyInfo) return ReflectionExtensions.GetValue((PropertyInfo)MemberInfo, obj); return ((FieldInfo)MemberInfo).GetValue(obj); } public string GetName() { if (CustomAttributes.JsonPropertyAttribute != null && !string.IsNullOrEmpty(CustomAttributes.JsonPropertyAttribute.PropertyName)) return CustomAttributes.JsonPropertyAttribute.PropertyName; if (CustomAttributes.DataContractAttribute != null) { dynamic val = CustomAttributes.DataMemberAttribute != null; if ((val ? false : true) ? val : (val & !string.IsNullOrEmpty(CustomAttributes.DataMemberAttribute.Name))) return (string)CustomAttributes.DataMemberAttribute.Name; } return MemberInfo.Name; } } public class CustomAttributes { public JsonIgnoreAttribute JsonIgnoreAttribute { get; } public JsonPropertyAttribute JsonPropertyAttribute { get; } public Attribute DataContractAttribute { get; } public dynamic DataMemberAttribute { get; } public CustomAttributes(JsonIgnoreAttribute jsonIgnoreAttribute, JsonPropertyAttribute jsonPropertyAttribute, Attribute dataContractAttribute, Attribute dataMemberAttribute) { JsonIgnoreAttribute = jsonIgnoreAttribute; JsonPropertyAttribute = jsonPropertyAttribute; DataContractAttribute = dataContractAttribute; DataMemberAttribute = dataMemberAttribute; } } private static readonly Dictionary<Type, IList<PropertyOrField>> PropertyCacheByType = new Dictionary<Type, IList<PropertyOrField>>(); private static readonly Dictionary<Type, Attribute> DataContractAttributeCacheByType = new Dictionary<Type, Attribute>(); public static IEnumerable<PropertyOrField> GetPropertiesAndFields(Type type) { lock (PropertyCacheByType) { if (!PropertyCacheByType.ContainsKey(type)) { IEnumerable<PropertyInfo> source = type.GetTypeInfo().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Where(delegate(PropertyInfo p) { if (!(p.GetGetMethod(true)?.IsAssembly ?? false) && !(p.GetGetMethod(true)?.IsPublic ?? false) && !(p.GetSetMethod(true)?.IsAssembly ?? false)) return p.GetSetMethod(true)?.IsPublic ?? false; return true; }); List<PropertyOrField> value = (from p in Enumerable.Concat(second: type.GetTypeInfo().GetFields(BindingFlags.Instance | BindingFlags.Public), first: source.OfType<MemberInfo>()) select new PropertyOrField(p, GetCustomAttributes(p))).ToList(); PropertyCacheByType[type] = value; } return PropertyCacheByType[type]; } } private static CustomAttributes GetCustomAttributes(MemberInfo property) { JsonIgnoreAttribute jsonIgnoreAttribute = null; JsonPropertyAttribute jsonPropertyAttribute = null; Attribute dataMemberAttribute = null; foreach (Attribute item in property.GetCustomAttributes(true).OfType<Attribute>()) { if (item is JsonIgnoreAttribute) jsonIgnoreAttribute = (item as JsonIgnoreAttribute); else if (item is JsonPropertyAttribute) { jsonPropertyAttribute = (item as JsonPropertyAttribute); } else if (item.GetType().Name == "DataMemberAttribute") { dataMemberAttribute = item; } } return new CustomAttributes(jsonIgnoreAttribute, jsonPropertyAttribute, GetDataContractAttribute(property.DeclaringType), dataMemberAttribute); } public static Attribute GetDataContractAttribute(Type type) { lock (DataContractAttributeCacheByType) { if (!DataContractAttributeCacheByType.ContainsKey(type)) { Attribute value = ReflectionExtensions.GetCustomAttributes(type.GetTypeInfo(), true).SingleOrDefault((Attribute a) => a.GetType().Name == "DataContractAttribute"); DataContractAttributeCacheByType[type] = value; } return DataContractAttributeCacheByType[type]; } } } }