JsonPropertyInfo<T>
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace System.Text.Json.Serialization.Metadata
{
internal sealed class JsonPropertyInfo<T> : JsonPropertyInfo
{
private Func<object, T> _typedGet;
private Action<object, T> _typedSet;
private Func<object, T, bool> _shouldSerializeTyped;
private JsonConverter<T> _typedEffectiveConverter;
internal new Func<object, T> Get {
get {
return _typedGet;
}
set {
SetGetter(value);
}
}
internal new Action<object, T> Set {
get {
return _typedSet;
}
set {
SetSetter(value);
}
}
internal new Func<object, T, bool> ShouldSerialize {
get {
return _shouldSerializeTyped;
}
set {
SetShouldSerialize(value);
}
}
internal override object DefaultValue => default(T);
internal override bool PropertyTypeCanBeNull => default(T) == null;
internal new JsonConverter<T> EffectiveConverter => _typedEffectiveConverter;
internal JsonPropertyInfo(Type declaringType, JsonTypeInfo declaringTypeInfo, JsonSerializerOptions options)
: base(declaringType, typeof(T), declaringTypeInfo, options)
{
}
private protected override void SetGetter(Delegate getter)
{
if ((object)getter == null) {
_typedGet = null;
_untypedGet = null;
} else {
Func<object, T> typedGetter = getter as Func<object, T>;
if (typedGetter != null) {
_typedGet = typedGetter;
Func<object, object> func = getter as Func<object, object>;
_untypedGet = ((func != null) ? func : ((Func<object, object>)((object obj) => typedGetter(obj))));
} else {
Func<object, object> untypedGet = (Func<object, object>)getter;
_typedGet = ((object obj) => (T)untypedGet(obj));
_untypedGet = untypedGet;
}
}
}
private protected override void SetSetter(Delegate setter)
{
if ((object)setter == null) {
_typedSet = null;
_untypedSet = null;
} else {
Action<object, T> typedSetter = setter as Action<object, T>;
if (typedSetter != null) {
_typedSet = typedSetter;
Action<object, object> action = setter as Action<object, object>;
_untypedSet = ((action != null) ? action : ((Action<object, object>)delegate(object obj, object value) {
typedSetter(obj, (T)value);
}));
} else {
Action<object, object> untypedSet = (Action<object, object>)setter;
_typedSet = delegate(object obj, T value) {
untypedSet(obj, value);
};
_untypedSet = untypedSet;
}
}
}
private protected override void SetShouldSerialize(Delegate predicate)
{
if ((object)predicate == null) {
_shouldSerializeTyped = null;
_shouldSerialize = null;
} else {
Func<object, T, bool> typedPredicate = predicate as Func<object, T, bool>;
if (typedPredicate != null) {
_shouldSerializeTyped = typedPredicate;
Func<object, object, bool> func = typedPredicate as Func<object, object, bool>;
_shouldSerialize = ((func != null) ? func : ((Func<object, object, bool>)((object obj, object value) => typedPredicate(obj, (T)value))));
} else {
Func<object, object, bool> untypedPredicate = (Func<object, object, bool>)predicate;
_shouldSerializeTyped = ((object obj, T value) => untypedPredicate(obj, value));
_shouldSerialize = untypedPredicate;
}
}
}
private protected override void DetermineMemberAccessors(MemberInfo memberInfo)
{
PropertyInfo propertyInfo = memberInfo as PropertyInfo;
if ((object)propertyInfo == null) {
FieldInfo fieldInfo = memberInfo as FieldInfo;
if ((object)fieldInfo != null) {
Get = JsonSerializerOptions.MemberAccessorStrategy.CreateFieldGetter<T>(fieldInfo);
if (!fieldInfo.IsInitOnly)
Set = JsonSerializerOptions.MemberAccessorStrategy.CreateFieldSetter<T>(fieldInfo);
}
} else {
bool flag = CustomAttributeExtensions.GetCustomAttribute<JsonIncludeAttribute>((MemberInfo)propertyInfo, false) != null;
MethodInfo getMethod = propertyInfo.GetMethod;
if (getMethod != (MethodInfo)null && (getMethod.IsPublic | flag))
Get = JsonSerializerOptions.MemberAccessorStrategy.CreatePropertyGetter<T>(propertyInfo);
MethodInfo setMethod = propertyInfo.SetMethod;
if (setMethod != (MethodInfo)null && (setMethod.IsPublic | flag))
Set = JsonSerializerOptions.MemberAccessorStrategy.CreatePropertySetter<T>(propertyInfo);
}
}
internal JsonPropertyInfo(JsonPropertyInfoValues<T> propertyInfo, JsonSerializerOptions options)
: this(propertyInfo.DeclaringType, (JsonTypeInfo)null, options)
{
string text = (propertyInfo.JsonPropertyName != null) ? propertyInfo.JsonPropertyName : ((options.PropertyNamingPolicy != null) ? options.PropertyNamingPolicy.ConvertName(propertyInfo.PropertyName) : propertyInfo.PropertyName);
if (text == null)
ThrowHelper.ThrowInvalidOperationException_SerializerPropertyNameNull(this);
base.Name = text;
base.MemberName = propertyInfo.PropertyName;
base.MemberType = (propertyInfo.IsProperty ? MemberTypes.Property : MemberTypes.Field);
base.SrcGen_IsPublic = propertyInfo.IsPublic;
base.SrcGen_HasJsonInclude = propertyInfo.HasJsonInclude;
base.IsExtensionData = propertyInfo.IsExtensionData;
base.CustomConverter = propertyInfo.Converter;
JsonIgnoreCondition? ignoreCondition = propertyInfo.IgnoreCondition;
JsonIgnoreCondition jsonIgnoreCondition = JsonIgnoreCondition.Always;
if (!((ignoreCondition.GetValueOrDefault() == jsonIgnoreCondition) & ignoreCondition.HasValue)) {
Get = propertyInfo.Getter;
Set = propertyInfo.Setter;
}
base.IgnoreCondition = propertyInfo.IgnoreCondition;
base.JsonTypeInfo = propertyInfo.PropertyTypeInfo;
base.NumberHandling = propertyInfo.NumberHandling;
}
private protected override void DetermineEffectiveConverter(JsonTypeInfo jsonTypeInfo)
{
_typedEffectiveConverter = (JsonConverter<T>)(_effectiveConverter = (base.Options.ExpandConverterFactory(base.CustomConverter, base.PropertyType)?.CreateCastingConverter<T>() ?? ((JsonTypeInfo<T>)jsonTypeInfo).EffectiveConverter));
}
internal override object GetValueAsObject(object obj)
{
if (base.IsForTypeInfo)
return obj;
return Get(obj);
}
internal override bool GetMemberAndWriteJson(object obj, ref WriteStack state, Utf8JsonWriter writer)
{
T value = Get(obj);
if (!EffectiveConverter.IsValueType && base.Options.ReferenceHandlingStrategy == ReferenceHandlingStrategy.IgnoreCycles && value != null && !state.IsContinuation && EffectiveConverter.ConverterStrategy != ConverterStrategy.Value && state.ReferenceResolver.ContainsReferenceForCycleDetection(value))
value = default(T);
if (base.IgnoreDefaultValuesOnWrite) {
if (IsDefaultValue(value))
return true;
} else {
Func<object, T, bool> shouldSerialize = ShouldSerialize;
if (shouldSerialize != null && !shouldSerialize(obj, value))
return true;
}
if (value == null) {
if (EffectiveConverter.HandleNullOnWrite) {
if ((int)state.Current.PropertyState < 2) {
state.Current.PropertyState = StackFramePropertyState.Name;
writer.WritePropertyNameSection(base.EscapedNameSection);
}
int currentDepth = writer.CurrentDepth;
EffectiveConverter.Write(writer, value, base.Options);
if (currentDepth != writer.CurrentDepth)
ThrowHelper.ThrowJsonException_SerializationConverterWrite(EffectiveConverter);
} else
writer.WriteNullSection(base.EscapedNameSection);
return true;
}
if ((int)state.Current.PropertyState < 2) {
state.Current.PropertyState = StackFramePropertyState.Name;
writer.WritePropertyNameSection(base.EscapedNameSection);
}
return EffectiveConverter.TryWrite(writer, ref value, base.Options, ref state);
}
internal override bool GetMemberAndWriteJsonExtensionData(object obj, ref WriteStack state, Utf8JsonWriter writer)
{
T val = Get(obj);
Func<object, T, bool> shouldSerialize = ShouldSerialize;
if (shouldSerialize != null && !shouldSerialize(obj, val))
return true;
if (val != null)
return EffectiveConverter.TryWriteDataExtensionProperty(writer, val, base.Options, ref state);
return true;
}
internal override bool ReadJsonAndSetMember(object obj, [System.Runtime.CompilerServices.ScopedRef] ref ReadStack state, ref Utf8JsonReader reader)
{
bool flag = reader.TokenType == JsonTokenType.Null;
bool flag2;
if (flag && !EffectiveConverter.HandleNullOnRead && !state.IsContinuation) {
if (default(T) != null)
ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(EffectiveConverter.TypeToConvert);
if (!base.IgnoreNullTokensOnRead)
Set(obj, default(T));
flag2 = true;
state.Current.MarkRequiredPropertyAsRead(this);
} else if (EffectiveConverter.CanUseDirectReadOrWrite && !state.Current.NumberHandling.HasValue) {
if (!flag || !base.IgnoreNullTokensOnRead || default(T) != null) {
T arg = EffectiveConverter.Read(ref reader, base.PropertyType, base.Options);
Set(obj, arg);
}
flag2 = true;
state.Current.MarkRequiredPropertyAsRead(this);
} else {
flag2 = true;
if (!flag || !base.IgnoreNullTokensOnRead || default(T) != null || state.IsContinuation) {
flag2 = EffectiveConverter.TryRead(ref reader, base.PropertyType, base.Options, ref state, out T value);
if (flag2) {
Set(obj, value);
state.Current.MarkRequiredPropertyAsRead(this);
}
}
}
return flag2;
}
internal override bool ReadJsonAsObject([System.Runtime.CompilerServices.ScopedRef] ref ReadStack state, ref Utf8JsonReader reader, out object value)
{
bool result;
if (reader.TokenType == JsonTokenType.Null && !EffectiveConverter.HandleNullOnRead && !state.IsContinuation) {
if (default(T) != null)
ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(EffectiveConverter.TypeToConvert);
value = default(T);
result = true;
} else if (EffectiveConverter.CanUseDirectReadOrWrite && !state.Current.NumberHandling.HasValue) {
value = EffectiveConverter.Read(ref reader, base.PropertyType, base.Options);
result = true;
} else {
result = EffectiveConverter.TryRead(ref reader, base.PropertyType, base.Options, ref state, out T value2);
value = value2;
}
return result;
}
private protected override void ConfigureIgnoreCondition(JsonIgnoreCondition? ignoreCondition)
{
if (ignoreCondition.HasValue) {
switch (ignoreCondition.GetValueOrDefault()) {
case JsonIgnoreCondition.Never:
ShouldSerialize = ((object _, T value) => true);
break;
case JsonIgnoreCondition.Always:
ShouldSerialize = ((object _, T value) => false);
break;
case JsonIgnoreCondition.WhenWritingNull:
if (PropertyTypeCanBeNull) {
ShouldSerialize = delegate(object _, T value) {
if (default(T) != null)
return !EqualityComparer<T>.Default.Equals(default(T), value);
return value != null;
};
base.IgnoreDefaultValuesOnWrite = true;
} else
ThrowHelper.ThrowInvalidOperationException_IgnoreConditionOnValueTypeInvalid(base.MemberName, base.DeclaringType);
break;
case JsonIgnoreCondition.WhenWritingDefault:
ShouldSerialize = delegate(object _, T value) {
if (default(T) != null)
return !EqualityComparer<T>.Default.Equals(default(T), value);
return value != null;
};
base.IgnoreDefaultValuesOnWrite = true;
break;
}
}
}
private static bool IsDefaultValue(T value)
{
if (default(T) != null)
return EqualityComparer<T>.Default.Equals(default(T), value);
return value == null;
}
}
}