@@ -933,7 +933,9 @@ private string GetTSType(PropertyInfo property)
933933 propertyType = propertyType . GetElementType ( ) ! ;
934934 }
935935
936- string tsType = GetTSType ( propertyType , _nullabilityContext . Create ( property ) ) ;
936+ string tsType = GetTSType (
937+ propertyType ,
938+ FixNullability ( _nullabilityContext . Create ( property ) ) ) ;
937939
938940 if ( tsType == "unknown" || tsType . Contains ( "unknown" ) )
939941 {
@@ -1001,7 +1003,8 @@ private string GetTSType(ParameterInfo parameter)
10011003 }
10021004
10031005 tsType = GetTSType (
1004- parameter . ParameterType , _nullabilityContext . Create ( parameter ) ) ;
1006+ parameter . ParameterType ,
1007+ FixNullability ( _nullabilityContext . Create ( parameter ) ) ) ;
10051008 return $ "{{ { resultName } : { tsType } , { outProperties } }}";
10061009 }
10071010 }
@@ -1013,7 +1016,7 @@ private string GetTSType(ParameterInfo parameter)
10131016 parameterType = parameterType . GetElementType ( ) ! ;
10141017 }
10151018
1016- tsType = GetTSType ( parameterType , _nullabilityContext . Create ( parameter ) ) ;
1019+ tsType = GetTSType ( parameterType , FixNullability ( _nullabilityContext . Create ( parameter ) ) ) ;
10171020 if ( tsType == "unknown" || tsType . Contains ( "unknown" ) )
10181021 {
10191022 string className = parameter . Member . DeclaringType ! . Name ;
@@ -1043,6 +1046,34 @@ private string GetTSType(ParameterInfo parameter)
10431046 return tsType ;
10441047 }
10451048
1049+ /// <summary>
1050+ /// The generator loads all referenced types in a separate MetadataLoadContext,
1051+ /// which causes a problem with NullabilityInfoContext when it tries to detect
1052+ /// whether a type is a value type, because the referenced ValueType type is not
1053+ /// the same as the system ValueType type. This method overrides the nullability
1054+ /// state for value types, which can never be nullable. (Note Nullable<T> is itself
1055+ /// a non-nullable value type; it is handled by the generator as a special case.)
1056+ /// </summary>
1057+ private static NullabilityInfo FixNullability ( NullabilityInfo nullability )
1058+ {
1059+ if ( nullability . Type . BaseType ? . FullName == typeof ( ValueType ) . FullName )
1060+ {
1061+ // Use reflection to override these properties which have internal setters.
1062+ // There is no public constructor and no other way to set these properties.
1063+ typeof ( NullabilityInfo ) . GetProperty ( nameof ( NullabilityInfo . ReadState ) ) !
1064+ . SetValue ( nullability , NullabilityState . NotNull ) ;
1065+ typeof ( NullabilityInfo ) . GetProperty ( nameof ( NullabilityInfo . WriteState ) ) !
1066+ . SetValue ( nullability , NullabilityState . NotNull ) ;
1067+ }
1068+
1069+ for ( int i = 0 ; i < nullability . GenericTypeArguments . Length ; i ++ )
1070+ {
1071+ FixNullability ( nullability . GenericTypeArguments [ i ] ) ;
1072+ }
1073+
1074+ return nullability ;
1075+ }
1076+
10461077 private string GetTSType ( Type type , NullabilityInfo ? nullability )
10471078 {
10481079 string tsType = "unknown" ;
0 commit comments