@@ -1410,6 +1410,25 @@ static IEnumerable<Instruction> SetBinding(VariableDefinition parent, FieldRefer
14101410
14111411 static bool CanSetValue ( FieldReference bpRef , bool attached , INode node , IXmlLineInfo iXmlLineInfo , ILContext context )
14121412 {
1413+ static bool CanSetValue ( TypeReference bpTypeRef , VariableDefinition varValue , ILContext context , IXmlLineInfo iXmlLineInfo )
1414+ {
1415+ // If it's an attached BP, there's no second chance to handle IMarkupExtensions, so we try here.
1416+ // Worst case scenario ? InvalidCastException at runtime
1417+ if ( varValue . VariableType . FullName == "System.Object" )
1418+ return true ;
1419+ var implicitOperator = varValue . VariableType . GetImplicitOperatorTo ( context . Cache , bpTypeRef , context . Body . Method . Module ) ;
1420+ if ( implicitOperator != null )
1421+ return true ;
1422+
1423+ //as we're in the SetValue Scenario, we can accept value types, they'll be boxed
1424+ if ( varValue . VariableType . IsValueType && bpTypeRef . FullName == "System.Object" )
1425+ return true ;
1426+
1427+ if ( varValue . VariableType . InheritsFromOrImplements ( context . Cache , bpTypeRef ) || varValue . VariableType . FullName == "System.Object" )
1428+ return true ;
1429+ return false ;
1430+ }
1431+
14131432 var module = context . Body . Method . Module ;
14141433
14151434 if ( bpRef == null )
@@ -1424,22 +1443,23 @@ static bool CanSetValue(FieldReference bpRef, bool attached, INode node, IXmlLin
14241443 if ( ! context . Variables . TryGetValue ( elementNode , out VariableDefinition varValue ) )
14251444 return false ;
14261445
1446+
14271447 var bpTypeRef = bpRef . GetBindablePropertyType ( context . Cache , iXmlLineInfo , module ) ;
1428- // If it's an attached BP, there's no second chance to handle IMarkupExtensions, so we try here.
1429- // Worst case scenario ? InvalidCastException at runtime
1430- if ( varValue . VariableType . FullName == "System.Object" )
1431- return true ;
1432- var implicitOperator = varValue . VariableType . GetImplicitOperatorTo ( context . Cache , bpTypeRef , module ) ;
1433- if ( implicitOperator != null )
1434- return true ;
14351448
1436- //as we're in the SetValue Scenario, we can accept value types, they'll be boxed
1437- if ( varValue . VariableType . IsValueType && bpTypeRef . FullName == "System.Object" )
1449+ if ( CanSetValue ( bpTypeRef , varValue , context , iXmlLineInfo ) )
14381450 return true ;
14391451
1440- return varValue . VariableType . InheritsFromOrImplements ( context . Cache , bpTypeRef ) || varValue . VariableType . FullName == "System.Object" ;
1452+ if ( bpTypeRef . ResolveCached ( context . Cache ) . FullName == "System.Nullable`1" )
1453+ {
1454+ bpTypeRef = ( ( GenericInstanceType ) bpTypeRef ) . GenericArguments [ 0 ] ;
1455+ if ( CanSetValue ( bpTypeRef , varValue , context , iXmlLineInfo ) )
1456+ return true ;
1457+ }
1458+
1459+ return false ;
14411460 }
14421461
1462+
14431463 static bool CanGetValue ( VariableDefinition parent , FieldReference bpRef , bool attached , IXmlLineInfo iXmlLineInfo , ILContext context , out TypeReference propertyType )
14441464 {
14451465 var module = context . Body . Method . Module ;
@@ -1483,32 +1503,37 @@ static IEnumerable<Instruction> SetValue(VariableDefinition parent, FieldReferen
14831503 var @else = Create ( OpCodes . Nop ) ;
14841504 var endif = Create ( OpCodes . Nop ) ;
14851505
1486- if ( context . Variables [ elementNode ] . VariableType . FullName == "System.Object" )
1506+
1507+ var varValue = context . Variables [ elementNode ] ;
1508+ if ( varValue . VariableType . FullName == "System.Object" )
14871509 {
14881510 //if(value != null && value.GetType().IsAssignableFrom(typeof(BindingBase)))
1489- yield return Create ( Ldloc , context . Variables [ elementNode ] ) ;
1511+ yield return Create ( Ldloc , varValue ) ;
14901512 yield return Create ( Brfalse , @else ) ;
1491-
14921513 yield return Create ( Ldtoken , module . ImportReference ( context . Cache , ( "Microsoft.Maui.Controls" , "Microsoft.Maui.Controls" , "BindingBase" ) ) ) ;
14931514 yield return Create ( Call , module . ImportMethodReference ( context . Cache , ( "mscorlib" , "System" , "Type" ) , methodName : "GetTypeFromHandle" , parameterTypes : new [ ] { ( "mscorlib" , "System" , "RuntimeTypeHandle" ) } , isStatic : true ) ) ;
1494- yield return Create ( Ldloc , context . Variables [ elementNode ] ) ;
1515+ yield return Create ( Ldloc , varValue ) ;
14951516 yield return Create ( Callvirt , module . ImportMethodReference ( context . Cache , ( "mscorlib" , "System" , "Object" ) , methodName : "GetType" , paramCount : 0 ) ) ;
14961517 yield return Create ( Callvirt , module . ImportMethodReference ( context . Cache , ( "mscorlib" , "System" , "Type" ) , methodName : "IsAssignableFrom" , parameterTypes : new [ ] { ( "mscorlib" , "System" , "Type" ) } ) ) ;
14971518 yield return Create ( Brfalse , @else ) ;
14981519 //then
1499- yield return Create ( Ldloc , context . Variables [ elementNode ] ) ;
1520+ yield return Create ( Ldloc , varValue ) ;
15001521 yield return Create ( Br , endif ) ;
15011522 //else
15021523 yield return @else ;
15031524 }
15041525 var bpTypeRef = bpRef . GetBindablePropertyType ( context . Cache , iXmlLineInfo , module ) ;
1505- foreach ( var instruction in context . Variables [ elementNode ] . LoadAs ( context . Cache , bpTypeRef , module ) )
1526+ foreach ( var instruction in varValue . LoadAs ( context . Cache , bpTypeRef , module ) )
15061527 yield return instruction ;
15071528 if ( bpTypeRef . IsValueType )
1529+ {
1530+ if ( bpTypeRef . ResolveCached ( context . Cache ) . FullName == "System.Nullable`1"
1531+ && TypeRefComparer . Default . Equals ( varValue . VariableType , ( ( GenericInstanceType ) bpTypeRef ) . GenericArguments [ 0 ] ) )
1532+ bpTypeRef = ( ( GenericInstanceType ) bpTypeRef ) . GenericArguments [ 0 ] ;
15081533 yield return Create ( Box , module . ImportReference ( bpTypeRef ) ) ;
1509-
1534+ }
15101535 //endif
1511- if ( context . Variables [ elementNode ] . VariableType . FullName == "System.Object" )
1536+ if ( varValue . VariableType . FullName == "System.Object" )
15121537 yield return endif ;
15131538
15141539 }
0 commit comments