4
4
using System . Collections . Generic ;
5
5
using System . Diagnostics ;
6
6
using System . Globalization ;
7
+ using System . Linq ;
7
8
using System . Reflection ;
8
9
using System . Text . Json . Reflection ;
9
10
using System . Text . Json . Serialization ;
@@ -699,7 +700,7 @@ private static string GeneratePropMetadataInitFunc(TypeGenerationSpec typeGenera
699
700
{
700
701
{ DefaultIgnoreCondition : JsonIgnoreCondition . Always } => "null" ,
701
702
{ CanUseSetter : true , IsInitOnlySetter : true }
702
- => @$ "static (obj, value) => throw new { InvalidOperationExceptionTypeRef } (""{ ExceptionMessages . InitOnlyPropertyDeserializationNotSupported } "")",
703
+ => @$ "static (obj, value) => throw new { InvalidOperationExceptionTypeRef } (""{ ExceptionMessages . InitOnlyPropertySetterNotSupported } "")",
703
704
{ CanUseSetter : true } when typeGenerationSpec . IsValueType
704
705
=> $@ "static (obj, value) => { UnsafeTypeRef } .Unbox<{ declaringTypeCompilableName } >(obj).{ nameSpecifiedInSourceCode } = value!",
705
706
{ CanUseSetter : true }
@@ -743,7 +744,8 @@ private static string GeneratePropMetadataInitFunc(TypeGenerationSpec typeGenera
743
744
744
745
{ JsonPropertyInfoTypeRef } { propertyInfoVarName } = { JsonMetadataServicesTypeRef } .CreatePropertyInfo<{ memberTypeCompilableName } >({ OptionsLocalVariableName } , { infoVarName } );" ) ;
745
746
746
- if ( memberMetadata . IsRequired )
747
+ if ( memberMetadata . HasJsonRequiredAttribute ||
748
+ ( memberMetadata . IsRequired && ! typeGenerationSpec . ConstructorSetsRequiredParameters ) )
747
749
{
748
750
sb. Append ( $@ "
749
751
{ propertyInfoVarName } .IsRequired = true;" ) ;
@@ -772,7 +774,8 @@ string GenerateCtorParamMetadataInitFunc(TypeGenerationSpec typeGenerationSpec)
772
774
Debug. Assert ( typeGenerationSpec . CtorParamGenSpecArray != null ) ;
773
775
774
776
ParameterGenerationSpec[ ] parameters = typeGenerationSpec . CtorParamGenSpecArray ;
775
- int paramCount = parameters. Length;
777
+ List < PropertyInitializerGenerationSpec > ? propertyInitializers = typeGenerationSpec . PropertyInitializerSpecList ;
778
+ int paramCount = parameters. Length + ( propertyInitializers ? . Count ( propInit => ! propInit . MatchesConstructorParameter ) ?? 0 ) ;
776
779
Debug . Assert ( paramCount > 0 ) ;
777
780
778
781
StringBuilder sb = new ( $@ "
@@ -782,10 +785,9 @@ string GenerateCtorParamMetadataInitFunc(TypeGenerationSpec typeGenerationSpec)
782
785
{ JsonParameterInfoValuesTypeRef } [] { parametersVarName } = new { JsonParameterInfoValuesTypeRef } [{ paramCount } ];
783
786
{ JsonParameterInfoValuesTypeRef } info;
784
787
" ) ;
785
-
786
- for ( int i = 0 ; i < paramCount ; i++ )
788
+ foreach ( ParameterGenerationSpec spec in parameters)
787
789
{
788
- ParameterInfo reflectionInfo = parameters [ i ] . ParameterInfo ;
790
+ ParameterInfo reflectionInfo = spec . ParameterInfo;
789
791
Type parameterType = reflectionInfo. ParameterType;
790
792
string parameterTypeRef = parameterType. GetCompilableName( ) ;
791
793
@@ -801,8 +803,31 @@ string GenerateCtorParamMetadataInitFunc(TypeGenerationSpec typeGenerationSpec)
801
803
HasDefaultValue = { FormatBool ( reflectionInfo . HasDefaultValue ) } ,
802
804
DefaultValue = { defaultValueAsStr }
803
805
} } ;
804
- { parametersVarName } [ { i } ] = { InfoVarName } ;
806
+ { parametersVarName} [ { spec . ParameterIndex } ] = { InfoVarName } ;
807
+ ");
808
+ }
809
+
810
+ if ( propertyInitializers != null )
811
+ {
812
+ Debug . Assert ( propertyInitializers . Count > 0 ) ;
813
+
814
+ foreach ( PropertyInitializerGenerationSpec spec in propertyInitializers)
815
+ {
816
+ if ( spec . MatchesConstructorParameter )
817
+ continue;
818
+
819
+ sb. Append ( @$ "
820
+ { InfoVarName } = new()
821
+ {{
822
+ Name = ""{ spec . Property . JsonPropertyName ?? spec . Property . ClrName } "",
823
+ ParameterType = typeof({ spec . Property . TypeGenerationSpec . TypeRef } ),
824
+ Position = { spec . ParameterIndex } ,
825
+ HasDefaultValue = false,
826
+ DefaultValue = default({ spec . Property . TypeGenerationSpec . TypeRef } ),
827
+ }};
828
+ { parametersVarName } [{ spec . ParameterIndex } ] = { InfoVarName } ;
805
829
" ) ;
830
+ }
806
831
}
807
832
808
833
sb. Append ( @$ "
@@ -959,27 +984,43 @@ private static bool ShouldIncludePropertyForFastPath(PropertyGenerationSpec prop
959
984
private static string GetParameterizedCtorInvocationFunc( TypeGenerationSpec typeGenerationSpec)
960
985
{
961
986
Debug. Assert( typeGenerationSpec. CtorParamGenSpecArray != null ) ;
962
-
963
987
ParameterGenerationSpec[ ] parameters = typeGenerationSpec . CtorParamGenSpecArray ;
964
- int paramCount = parameters . Length ;
965
- Debug . Assert ( paramCount != 0 ) ;
988
+ List < PropertyInitializerGenerationSpec > ? propertyInitializers = typeGenerationSpec . PropertyInitializerSpecList ;
966
989
967
990
const string ArgsVarName = "args" ;
968
- int lastIndex = paramCount - 1 ;
969
991
970
992
StringBuilder sb = new ( $ "static ({ ArgsVarName } ) => new { typeGenerationSpec . TypeRef } (") ;
971
993
972
- for ( int i = 0 ; i < lastIndex ; i ++ )
994
+ if ( parameters . Length > 0 )
973
995
{
974
- sb . Append ( $ "{ GetParamUnboxing ( parameters [ i ] , i ) } , ") ;
996
+ foreach ( ParameterGenerationSpec param in parameters)
997
+ {
998
+ int index = param . ParameterIndex ;
999
+ sb . Append ( $ "{ GetParamUnboxing ( param . ParameterInfo . ParameterType , index ) } , ") ;
1000
+ }
1001
+
1002
+ sb . Length -= 2 ; // delete the last ", " token
975
1003
}
976
1004
977
- sb . Append ( $ "{ GetParamUnboxing ( parameters [ lastIndex ] , lastIndex ) } )") ;
1005
+ sb . Append ( ')' ) ;
1006
+
1007
+ if ( propertyInitializers != null )
1008
+ {
1009
+ Debug . Assert ( propertyInitializers . Count > 0 ) ;
1010
+ sb. Append ( "{ " ) ;
1011
+ foreach ( PropertyInitializerGenerationSpec property in propertyInitializers)
1012
+ {
1013
+ sb. Append ( $ "{ property . Property . ClrName } = { GetParamUnboxing ( property . Property . TypeGenerationSpec . Type , property . ParameterIndex ) } , ") ;
1014
+ }
1015
+
1016
+ sb. Length -= 2 ; // delete the last ", " token
1017
+ sb . Append ( " }" ) ;
1018
+ }
978
1019
979
1020
return sb. ToString ( ) ;
980
1021
981
- static string GetParamUnboxing ( ParameterGenerationSpec spec , int index )
982
- => $ "({ spec . ParameterInfo . ParameterType . GetCompilableName ( ) } ){ ArgsVarName } [{ index } ]";
1022
+ static string GetParamUnboxing ( Type type , int index )
1023
+ => $ "({ type . GetCompilableName ( ) } ){ ArgsVarName } [{ index } ]";
983
1024
}
984
1025
985
1026
private string ? GetWriterMethod ( Type type )
0 commit comments