-
Notifications
You must be signed in to change notification settings - Fork 5.5k
Simplify JsonTypeInfo construction #67700
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -43,78 +43,89 @@ internal override void Initialize( | |
| bool isVirtual, | ||
| JsonConverter converter, | ||
| JsonIgnoreCondition? ignoreCondition, | ||
| JsonNumberHandling? parentTypeNumberHandling, | ||
| JsonSerializerOptions options) | ||
| JsonSerializerOptions options, | ||
| JsonTypeInfo? jsonTypeInfo = null) | ||
| { | ||
| base.Initialize( | ||
| parentClassType, | ||
| declaredPropertyType, | ||
| converterStrategy, | ||
| memberInfo, | ||
| isVirtual, | ||
| converter, | ||
| ignoreCondition, | ||
| parentTypeNumberHandling, | ||
| options); | ||
|
|
||
| switch (memberInfo) | ||
| Debug.Assert(converter != null); | ||
|
|
||
| PropertyType = declaredPropertyType; | ||
| ConverterStrategy = converterStrategy; | ||
| if (jsonTypeInfo != null) | ||
| { | ||
| case PropertyInfo propertyInfo: | ||
| { | ||
| bool useNonPublicAccessors = GetAttribute<JsonIncludeAttribute>(propertyInfo) != null; | ||
| JsonTypeInfo = jsonTypeInfo; | ||
| } | ||
|
|
||
| MethodInfo? getMethod = propertyInfo.GetMethod; | ||
| if (getMethod != null && (getMethod.IsPublic || useNonPublicAccessors)) | ||
| { | ||
| HasGetter = true; | ||
| Get = options.MemberAccessorStrategy.CreatePropertyGetter<T>(propertyInfo); | ||
| } | ||
| ConverterBase = converter; | ||
| Options = options; | ||
| DeclaringType = parentClassType; | ||
| MemberInfo = memberInfo; | ||
| IsVirtual = isVirtual; | ||
|
|
||
| MethodInfo? setMethod = propertyInfo.SetMethod; | ||
| if (setMethod != null && (setMethod.IsPublic || useNonPublicAccessors)) | ||
| if (memberInfo != null) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can actually embed the null check in the switch statement by doing something like switch (memberInfo)
{
case null:
IsForTypeInfo = true;
HasGetter = true;
HasSetter = true;
break;
case PropertyInfo propertyInfo:
...which should save you a tab of indentation :-)
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. but we also need to do: // TODO (perf): can we pre-compute some of these values during source gen?
_converterIsExternalAndPolymorphic = !converter.IsInternalConverter && PropertyType != converter.TypeToConvert;
PropertyTypeCanBeNull = PropertyType.CanBeNull();
_propertyTypeEqualsTypeToConvert = typeof(T) == PropertyType;
GetPolicies(ignoreCondition);
GetPolicies(ignoreCondition);for |
||
| { | ||
| switch (memberInfo) | ||
| { | ||
| case PropertyInfo propertyInfo: | ||
| { | ||
| HasSetter = true; | ||
| Set = options.MemberAccessorStrategy.CreatePropertySetter<T>(propertyInfo); | ||
| } | ||
| bool useNonPublicAccessors = GetAttribute<JsonIncludeAttribute>(propertyInfo) != null; | ||
|
|
||
| MemberType = MemberTypes.Property; | ||
| MethodInfo? getMethod = propertyInfo.GetMethod; | ||
| if (getMethod != null && (getMethod.IsPublic || useNonPublicAccessors)) | ||
| { | ||
| HasGetter = true; | ||
| Get = options.MemberAccessorStrategy.CreatePropertyGetter<T>(propertyInfo); | ||
| } | ||
|
|
||
| break; | ||
| } | ||
| MethodInfo? setMethod = propertyInfo.SetMethod; | ||
| if (setMethod != null && (setMethod.IsPublic || useNonPublicAccessors)) | ||
| { | ||
| HasSetter = true; | ||
| Set = options.MemberAccessorStrategy.CreatePropertySetter<T>(propertyInfo); | ||
| } | ||
|
|
||
| case FieldInfo fieldInfo: | ||
| { | ||
| Debug.Assert(fieldInfo.IsPublic); | ||
| MemberType = MemberTypes.Property; | ||
|
|
||
| HasGetter = true; | ||
| Get = options.MemberAccessorStrategy.CreateFieldGetter<T>(fieldInfo); | ||
| break; | ||
| } | ||
|
|
||
| if (!fieldInfo.IsInitOnly) | ||
| case FieldInfo fieldInfo: | ||
| { | ||
| HasSetter = true; | ||
| Set = options.MemberAccessorStrategy.CreateFieldSetter<T>(fieldInfo); | ||
| } | ||
| Debug.Assert(fieldInfo.IsPublic); | ||
|
|
||
| MemberType = MemberTypes.Field; | ||
| HasGetter = true; | ||
| Get = options.MemberAccessorStrategy.CreateFieldGetter<T>(fieldInfo); | ||
|
|
||
| break; | ||
| } | ||
| if (!fieldInfo.IsInitOnly) | ||
| { | ||
| HasSetter = true; | ||
| Set = options.MemberAccessorStrategy.CreateFieldSetter<T>(fieldInfo); | ||
| } | ||
|
|
||
| default: | ||
| { | ||
| IsForTypeInfo = true; | ||
| HasGetter = true; | ||
| HasSetter = true; | ||
| MemberType = MemberTypes.Field; | ||
|
|
||
| break; | ||
| } | ||
| } | ||
| break; | ||
| } | ||
|
|
||
| _converterIsExternalAndPolymorphic = !converter.IsInternalConverter && PropertyType != converter.TypeToConvert; | ||
| PropertyTypeCanBeNull = PropertyType.CanBeNull(); | ||
| _propertyTypeEqualsTypeToConvert = typeof(T) == PropertyType; | ||
| default: | ||
| { | ||
| Debug.Fail($"Invalid memberInfo type: {memberInfo.GetType().FullName}"); | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| // TODO (perf): can we pre-compute some of these values during source gen? | ||
| _converterIsExternalAndPolymorphic = !converter.IsInternalConverter && PropertyType != converter.TypeToConvert; | ||
| PropertyTypeCanBeNull = PropertyType.CanBeNull(); | ||
| _propertyTypeEqualsTypeToConvert = typeof(T) == PropertyType; | ||
|
|
||
| GetPolicies(ignoreCondition); | ||
| GetPolicies(ignoreCondition); | ||
| } | ||
| else | ||
| { | ||
| IsForTypeInfo = true; | ||
| HasGetter = true; | ||
| HasSetter = true; | ||
| } | ||
| } | ||
|
|
||
| internal void InitializeForSourceGen(JsonSerializerOptions options, JsonPropertyInfoValues<T> propertyInfo) | ||
|
|
@@ -189,30 +200,6 @@ internal void InitializeForSourceGen(JsonSerializerOptions options, JsonProperty | |
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Create a <see cref="JsonPropertyInfo"/> for a given Type. | ||
| /// See <seealso cref="JsonTypeInfo.PropertyInfoForTypeInfo"/>. | ||
| /// </summary> | ||
| internal override void InitializeForTypeInfo( | ||
| Type declaredType, | ||
| JsonTypeInfo runtimeTypeInfo, | ||
| JsonConverter converter, | ||
| JsonSerializerOptions options) | ||
| { | ||
| PropertyType = declaredType; | ||
| ConverterStrategy = converter.ConverterStrategy; | ||
| JsonTypeInfo = runtimeTypeInfo; | ||
| ConverterBase = converter; | ||
| Options = options; | ||
| IsForTypeInfo = true; | ||
| HasGetter = true; | ||
| HasSetter = true; | ||
| // TODO (perf): can we pre-compute some of these values during source gen? | ||
| _converterIsExternalAndPolymorphic = !converter.IsInternalConverter && declaredType != converter.TypeToConvert; | ||
| PropertyTypeCanBeNull = declaredType.CanBeNull(); | ||
| _propertyTypeEqualsTypeToConvert = typeof(T) == declaredType; | ||
| } | ||
|
|
||
| internal override JsonConverter ConverterBase | ||
| { | ||
| get | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -152,7 +152,7 @@ internal JsonTypeInfo? KeyTypeInfo | |
| /// TypeInfo (for the cases mentioned above). In addition, methods that have a JsonPropertyInfo argument would also likely | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FWIW I suspect the justification presented in the comments is obsolete:
Since all construction paths now require
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it's not that simple. Currently Read/WriteState heavly depend on converter being on PropertyInfo and that needs heavy refactoring in there. It's a huge mess as I've already gave it a quick attempt. |
||
| /// need to add an argument for JsonTypeInfo. | ||
| /// </remarks> | ||
| internal JsonPropertyInfo PropertyInfoForTypeInfo { get; set; } | ||
| internal JsonPropertyInfo PropertyInfoForTypeInfo { get; private set; } | ||
|
|
||
| /// <summary> | ||
| /// Returns a helper class used for computing the default value. | ||
|
|
@@ -162,24 +162,11 @@ internal JsonTypeInfo? KeyTypeInfo | |
|
|
||
| internal JsonNumberHandling? NumberHandling { get; set; } | ||
|
|
||
| internal JsonTypeInfo() | ||
| { | ||
| Debug.Assert(false, "This constructor should not be called."); | ||
| } | ||
|
|
||
| internal JsonTypeInfo(Type type, JsonSerializerOptions options!!) | ||
| { | ||
| Type = type; | ||
| Options = options; | ||
| // Setting this option is deferred to the initialization methods of the various metadada info types. | ||
| PropertyInfoForTypeInfo = null!; | ||
| } | ||
|
|
||
| internal JsonTypeInfo(Type type, JsonConverter converter, JsonSerializerOptions options) | ||
| { | ||
| Type = type; | ||
| Options = options; | ||
| PropertyInfoForTypeInfo = CreatePropertyInfoForTypeInfo(Type, converter, NumberHandling, Options); | ||
| PropertyInfoForTypeInfo = CreatePropertyInfoForTypeInfo(Type, converter, Options, this); | ||
| ElementType = converter.ElementType; | ||
|
|
||
| switch (PropertyInfoForTypeInfo.ConverterStrategy) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Am I right to understand that this parameter was not being used anywhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, we assign it in the
Configure()as it could get out of sync once we get into contract resolving which will allow to change this (also I think it might have not been used before my previous PR as well)