@@ -97,6 +97,7 @@ private void EmitGetCoreMethod()
9797 Expression . sectionPath ,
9898 writeOnSuccess : parsedValueExpr => _writer . WriteLine ( $ "return { parsedValueExpr } ;") ,
9999 checkForNullSectionValue : stringParsableType . StringParsableTypeKind is not StringParsableTypeKind . AssignFromSectionValue ,
100+ useDefaultValueIfSectionValueIsNull : false ,
100101 useIncrementalStringValueIdentifier : false ) ;
101102 }
102103 break ;
@@ -110,7 +111,7 @@ private void EmitGetCoreMethod()
110111 {
111112 if ( complexType . CanInstantiate )
112113 {
113- EmitBindingLogic ( complexType , Identifier . instance , Identifier . configuration , InitializationKind . Declaration ) ;
114+ EmitBindingLogic ( complexType , Identifier . instance , Identifier . configuration , InitializationKind . Declaration , ValueDefaulting . CallSetter ) ;
114115 _writer . WriteLine ( $ "return { Identifier . instance } ;") ;
115116 }
116117 else if ( type is ObjectSpec { InitExceptionMessage : string exMsg } )
@@ -173,6 +174,7 @@ private void EmitGetValueCoreMethod()
173174 Expression . sectionPath ,
174175 writeOnSuccess : ( parsedValueExpr ) => _writer . WriteLine ( $ "return { parsedValueExpr } ;") ,
175176 checkForNullSectionValue : false ,
177+ useDefaultValueIfSectionValueIsNull : false ,
176178 useIncrementalStringValueIdentifier : false ) ;
177179
178180 EmitEndBlock ( ) ;
@@ -207,7 +209,7 @@ private void EmitBindCoreMainMethod()
207209
208210 EmitStartBlock ( $ "{ conditionKindExpr } ({ Identifier . type } == typeof({ type . DisplayString } ))") ;
209211 _writer . WriteLine ( $ "var { Identifier . temp } = ({ effectiveType . DisplayString } ){ Identifier . instance } ;") ;
210- EmitBindingLogic ( type , Identifier . temp , Identifier . configuration , InitializationKind . None ) ;
212+ EmitBindingLogic ( type , Identifier . temp , Identifier . configuration , InitializationKind . None , ValueDefaulting . None ) ;
211213 _writer . WriteLine ( $ "return;") ;
212214 EmitEndBlock ( ) ;
213215 }
@@ -235,7 +237,7 @@ private void EmitBindCoreMethods()
235237 private void EmitBindCoreMethod ( ComplexTypeSpec type )
236238 {
237239 string objParameterExpression = $ "ref { type . DisplayString } { Identifier . instance } ";
238- EmitStartBlock ( @$ "public static void { nameof ( MethodsToGen_CoreBindingHelper . BindCore ) } ({ Identifier . IConfiguration } { Identifier . configuration } , { objParameterExpression } , { Identifier . BinderOptions } ? { Identifier . binderOptions } )") ;
240+ EmitStartBlock ( @$ "public static void { nameof ( MethodsToGen_CoreBindingHelper . BindCore ) } ({ Identifier . IConfiguration } { Identifier . configuration } , { objParameterExpression } , bool defaultValueIfNotFound, { Identifier . BinderOptions } ? { Identifier . binderOptions } )") ;
239241
240242 ComplexTypeSpec effectiveType = ( ComplexTypeSpec ) type . EffectiveType ;
241243 if ( effectiveType is EnumerableSpec enumerable )
@@ -334,8 +336,6 @@ private void EmitInitializeMethod(ObjectSpec type)
334336 void EmitBindImplForMember ( MemberSpec member )
335337 {
336338 TypeSpec memberType = member . Type ;
337- bool errorOnFailedBinding = member . ErrorOnFailedBinding ;
338-
339339 string parsedMemberDeclarationLhs = $ "{ memberType . DisplayString } { member . Name } ";
340340 string configKeyName = member . ConfigurationKeyName ;
341341 string parsedMemberAssignmentLhsExpr ;
@@ -344,7 +344,7 @@ void EmitBindImplForMember(MemberSpec member)
344344 {
345345 case ParsableFromStringSpec { StringParsableTypeKind : StringParsableTypeKind . AssignFromSectionValue } :
346346 {
347- if ( errorOnFailedBinding )
347+ if ( member is ParameterSpec parameter && parameter . ErrorOnFailedBinding )
348348 {
349349 string condition = $@ "if ({ Identifier . configuration } [""{ configKeyName } ""] is not { parsedMemberDeclarationLhs } )";
350350 EmitThrowBlock ( condition ) ;
@@ -377,11 +377,12 @@ void EmitBindImplForMember(MemberSpec member)
377377 member ,
378378 parsedMemberAssignmentLhsExpr ,
379379 sectionPathExpr : GetSectionPathFromConfigurationExpression ( configKeyName ) ,
380- canSet : true ) ;
380+ canSet : true ,
381+ InitializationKind . None ) ;
381382
382383 if ( canBindToMember )
383384 {
384- if ( errorOnFailedBinding )
385+ if ( member is ParameterSpec parameter && parameter . ErrorOnFailedBinding )
385386 {
386387 // Add exception logic for parameter ctors; must be present in configuration object.
387388 EmitThrowBlock ( condition : "else" ) ;
@@ -633,7 +634,7 @@ private void EmitPopulationImplForArray(EnumerableSpec type)
633634
634635 // Create list and bind elements.
635636 string tempIdentifier = GetIncrementalIdentifier ( Identifier . temp ) ;
636- EmitBindingLogic ( typeToInstantiate , tempIdentifier , Identifier . configuration , InitializationKind . Declaration ) ;
637+ EmitBindingLogic ( typeToInstantiate , tempIdentifier , Identifier . configuration , InitializationKind . Declaration , ValueDefaulting . None ) ;
637638
638639 // Resize array and add binded elements.
639640 _writer . WriteLine ( $$ """
@@ -661,6 +662,7 @@ private void EmitPopulationImplForEnumerableWithAdd(EnumerableSpec type)
661662 Expression . sectionPath ,
662663 ( parsedValueExpr ) => _writer . WriteLine ( $ "{ addExpr } ({ parsedValueExpr } );") ,
663664 checkForNullSectionValue : true ,
665+ useDefaultValueIfSectionValueIsNull : false ,
664666 useIncrementalStringValueIdentifier : false ) ;
665667 }
666668 break ;
@@ -671,7 +673,7 @@ private void EmitPopulationImplForEnumerableWithAdd(EnumerableSpec type)
671673 break ;
672674 case ComplexTypeSpec { CanInstantiate : true } complexType :
673675 {
674- EmitBindingLogic ( complexType , Identifier . value , Identifier . section , InitializationKind . Declaration ) ;
676+ EmitBindingLogic ( complexType , Identifier . value , Identifier . section , InitializationKind . Declaration , ValueDefaulting . None ) ;
675677 _writer . WriteLine ( $ "{ addExpr } ({ Identifier . value } );") ;
676678 }
677679 break ;
@@ -696,6 +698,7 @@ private void EmitBindCoreImplForDictionary(DictionarySpec type)
696698 Expression . sectionPath ,
697699 Emit_BindAndAddLogic_ForElement ,
698700 checkForNullSectionValue : false ,
701+ useDefaultValueIfSectionValueIsNull : false ,
699702 useIncrementalStringValueIdentifier : false ) ;
700703
701704 void Emit_BindAndAddLogic_ForElement ( string parsedKeyExpr )
@@ -710,6 +713,7 @@ void Emit_BindAndAddLogic_ForElement(string parsedKeyExpr)
710713 Expression . sectionPath ,
711714 writeOnSuccess : parsedValueExpr => _writer . WriteLine ( $ "{ instanceIdentifier } [{ parsedKeyExpr } ] = { parsedValueExpr } ;") ,
712715 checkForNullSectionValue : true ,
716+ useDefaultValueIfSectionValueIsNull : false ,
713717 useIncrementalStringValueIdentifier : false ) ;
714718 }
715719 break ;
@@ -746,7 +750,7 @@ void Emit_BindAndAddLogic_ForElement(string parsedKeyExpr)
746750 EmitObjectInit ( complexElementType , Identifier . element , InitializationKind . SimpleAssignment , Identifier . section ) ;
747751 EmitEndBlock ( ) ;
748752
749- EmitBindingLogic ( complexElementType , Identifier . element , Identifier . section , InitializationKind . None ) ;
753+ EmitBindingLogic ( complexElementType , Identifier . element , Identifier . section , InitializationKind . None , ValueDefaulting . None ) ;
750754 _writer . WriteLine ( $ "{ instanceIdentifier } [{ parsedKeyExpr } ] = { Identifier . element } ;") ;
751755 }
752756 break ;
@@ -774,7 +778,8 @@ private void EmitBindCoreImplForObject(ObjectSpec type)
774778 property ,
775779 memberAccessExpr : $ "{ containingTypeRef } .{ property . Name } ",
776780 GetSectionPathFromConfigurationExpression ( property . ConfigurationKeyName ) ,
777- canSet : property . CanSet ) ;
781+ canSet : property . CanSet ,
782+ InitializationKind . Declaration ) ;
778783 }
779784 }
780785 }
@@ -783,9 +788,11 @@ private bool EmitBindImplForMember(
783788 MemberSpec member ,
784789 string memberAccessExpr ,
785790 string sectionPathExpr ,
786- bool canSet )
791+ bool canSet ,
792+ InitializationKind initializationKind )
787793 {
788794 TypeSpec effectiveMemberType = member . Type . EffectiveType ;
795+
789796 string sectionParseExpr = GetSectionFromConfigurationExpression ( member . ConfigurationKeyName ) ;
790797
791798 switch ( effectiveMemberType )
@@ -794,19 +801,20 @@ private bool EmitBindImplForMember(
794801 {
795802 if ( canSet )
796803 {
797- bool checkForNullSectionValue = member is ParameterSpec
798- ? true
799- : stringParsableType . StringParsableTypeKind is not StringParsableTypeKind . AssignFromSectionValue ;
800-
801- string nullBangExpr = checkForNullSectionValue ? string . Empty : "!" ;
804+ bool useDefaultValueIfSectionValueIsNull =
805+ initializationKind == InitializationKind . Declaration &&
806+ member is PropertySpec &&
807+ member . Type . IsValueType &&
808+ member . Type . SpecKind is not TypeSpecKind . Nullable ;
802809
803810 EmitBlankLineIfRequired ( ) ;
804811 EmitBindingLogic (
805812 stringParsableType ,
806813 $@ "{ Identifier . configuration } [""{ member . ConfigurationKeyName } ""]",
807814 sectionPathExpr ,
808- writeOnSuccess : parsedValueExpr => _writer . WriteLine ( $ "{ memberAccessExpr } = { parsedValueExpr } { nullBangExpr } ;") ,
809- checkForNullSectionValue ,
815+ writeOnSuccess : parsedValueExpr => _writer . WriteLine ( $ "{ memberAccessExpr } = { parsedValueExpr } ;") ,
816+ checkForNullSectionValue : true ,
817+ useDefaultValueIfSectionValueIsNull ,
810818 useIncrementalStringValueIdentifier : true ) ;
811819 }
812820
@@ -906,14 +914,17 @@ private void EmitBindingLogicForComplexMember(
906914 targetObjAccessExpr ,
907915 configArgExpr ,
908916 initKind ,
909- writeOnSuccess ) ;
917+ ValueDefaulting . None ,
918+ writeOnSuccess
919+ ) ;
910920 }
911921
912922 private void EmitBindingLogic (
913923 ComplexTypeSpec type ,
914924 string memberAccessExpr ,
915925 string configArgExpr ,
916926 InitializationKind initKind ,
927+ ValueDefaulting valueDefaulting ,
917928 Action < string > ? writeOnSuccess = null )
918929 {
919930 if ( ! type . HasBindableMembers )
@@ -952,7 +963,7 @@ private void EmitBindingLogic(
952963
953964 void EmitBindingLogic ( string instanceToBindExpr , InitializationKind initKind )
954965 {
955- string bindCoreCall = $@ "{ nameof ( MethodsToGen_CoreBindingHelper . BindCore ) } ({ configArgExpr } , ref { instanceToBindExpr } , { Identifier . binderOptions } );";
966+ string bindCoreCall = $@ "{ nameof ( MethodsToGen_CoreBindingHelper . BindCore ) } ({ configArgExpr } , ref { instanceToBindExpr } , defaultValueIfNotFound: { FormatDefaultValueIfNotFound ( ) } , { Identifier . binderOptions } );";
956967
957968 if ( type . CanInstantiate )
958969 {
@@ -984,6 +995,8 @@ void EmitBindCoreCall()
984995 _writer . WriteLine ( bindCoreCall ) ;
985996 writeOnSuccess ? . Invoke ( instanceToBindExpr ) ;
986997 }
998+
999+ string FormatDefaultValueIfNotFound ( ) => valueDefaulting == ValueDefaulting . CallSetter ? "true" : "false" ;
9871000 }
9881001 }
9891002
@@ -993,6 +1006,7 @@ private void EmitBindingLogic(
9931006 string sectionPathExpr ,
9941007 Action < string > ? writeOnSuccess ,
9951008 bool checkForNullSectionValue ,
1009+ bool useDefaultValueIfSectionValueIsNull ,
9961010 bool useIncrementalStringValueIdentifier )
9971011 {
9981012 StringParsableTypeKind typeKind = type . StringParsableTypeKind ;
@@ -1018,6 +1032,14 @@ private void EmitBindingLogic(
10181032 EmitEndBlock ( ) ;
10191033 }
10201034
1035+ if ( useDefaultValueIfSectionValueIsNull )
1036+ {
1037+ parsedValueExpr = $ "default";
1038+ EmitStartBlock ( $ "else if (defaultValueIfNotFound)") ;
1039+ InvokeWriteOnSuccess ( ) ;
1040+ EmitEndBlock ( ) ;
1041+ }
1042+
10211043 void InvokeWriteOnSuccess ( ) => writeOnSuccess ? . Invoke ( parsedValueExpr ) ;
10221044 }
10231045
0 commit comments