ReflectionCache
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
namespace NJsonSchema.Infrastructure
{
internal static class ReflectionCache
{
public class Property
{
public PropertyInfo PropertyInfo { get; }
public CustomAttributes CustomAttributes { get; }
public Property(PropertyInfo propertyInfo, CustomAttributes customAttributes)
{
PropertyInfo = propertyInfo;
CustomAttributes = customAttributes;
}
public string GetName()
{
if (CustomAttributes.JsonPropertyAttribute != null && !string.IsNullOrEmpty(CustomAttributes.JsonPropertyAttribute.PropertyName))
return CustomAttributes.JsonPropertyAttribute.PropertyName;
if (CustomAttributes.DataContractAttribute != null && CustomAttributes.DataMemberAttribute != null && !string.IsNullOrEmpty(CustomAttributes.DataMemberAttribute.Name))
return CustomAttributes.DataMemberAttribute.Name;
return PropertyInfo.Name;
}
}
public class CustomAttributes
{
public JsonIgnoreAttribute JsonIgnoreAttribute { get; }
public JsonPropertyAttribute JsonPropertyAttribute { get; }
public DataContractAttribute DataContractAttribute { get; }
public DataMemberAttribute DataMemberAttribute { get; }
public CustomAttributes(JsonIgnoreAttribute jsonIgnoreAttribute, JsonPropertyAttribute jsonPropertyAttribute, DataContractAttribute dataContractAttribute, DataMemberAttribute dataMemberAttribute)
{
JsonIgnoreAttribute = jsonIgnoreAttribute;
JsonPropertyAttribute = jsonPropertyAttribute;
DataContractAttribute = dataContractAttribute;
DataMemberAttribute = dataMemberAttribute;
}
}
private static readonly Dictionary<Type, IList<Property>> PropertyCacheByType = new Dictionary<Type, IList<Property>>();
private static readonly Dictionary<Type, DataContractAttribute> DataContractAttributeCacheByType = new Dictionary<Type, DataContractAttribute>();
public static IEnumerable<Property> GetProperties(Type type)
{
lock (PropertyCacheByType) {
if (!PropertyCacheByType.ContainsKey(type)) {
List<Property> value = (from p in type.GetRuntimeProperties()
select new Property(p, GetCustomAttributes(p))).ToList();
PropertyCacheByType[type] = value;
}
return PropertyCacheByType[type];
}
}
private static CustomAttributes GetCustomAttributes(PropertyInfo property)
{
JsonIgnoreAttribute jsonIgnoreAttribute = null;
JsonPropertyAttribute jsonPropertyAttribute = null;
DataMemberAttribute dataMemberAttribute = null;
foreach (Attribute customAttribute in property.GetCustomAttributes()) {
if (customAttribute is JsonIgnoreAttribute)
jsonIgnoreAttribute = (customAttribute as JsonIgnoreAttribute);
else if (customAttribute is JsonPropertyAttribute) {
jsonPropertyAttribute = (customAttribute as JsonPropertyAttribute);
} else if (customAttribute is DataMemberAttribute) {
dataMemberAttribute = (customAttribute as DataMemberAttribute);
}
}
return new CustomAttributes(jsonIgnoreAttribute, jsonPropertyAttribute, GetDataContractAttribute(property.DeclaringType), dataMemberAttribute);
}
public static DataContractAttribute GetDataContractAttribute(Type type)
{
lock (DataContractAttributeCacheByType) {
if (!DataContractAttributeCacheByType.ContainsKey(type)) {
DataContractAttribute customAttribute = type.GetTypeInfo().GetCustomAttribute<DataContractAttribute>();
DataContractAttributeCacheByType[type] = customAttribute;
}
return DataContractAttributeCacheByType[type];
}
}
}
}