diff --git a/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v3.1/DeserializationStrictnessTests.Can_disallow_nulls_for_reference_value_objects.verified.txt b/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v3.1/DeserializationStrictnessTests.Can_disallow_nulls_for_reference_value_objects.verified.txt
new file mode 100644
index 0000000000..54a4599ab7
--- /dev/null
+++ b/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v3.1/DeserializationStrictnessTests.Can_disallow_nulls_for_reference_value_objects.verified.txt
@@ -0,0 +1,535 @@
+[
+// ------------------------------------------------------------------------------
+//
+// This code was generated by a source generator named Vogen (https://github.com/SteveDunn/Vogen)
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// ------------------------------------------------------------------------------
+
+// Suppress warnings about [Obsolete] member usage in generated code.
+#pragma warning disable CS0618
+
+// Suppress warnings for 'Override methods on comparable types'.
+#pragma warning disable CA1036
+
+// Suppress Error MA0097 : A class that implements IComparable or IComparable should override comparison operators
+#pragma warning disable MA0097
+
+// Suppress warning for 'The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source.'
+// The generator copies signatures from the BCL, e.g. for `TryParse`, and some of those have nullable annotations.
+#pragma warning disable CS8669
+
+// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
+#pragma warning disable CS1591
+
+namespace generator;
+
+public class VogenTypesFactory : global::System.Text.Json.Serialization.JsonConverterFactory
+{
+ public VogenTypesFactory() { }
+ private static readonly global::System.Collections.Generic.Dictionary> _lookup =
+ new global::System.Collections.Generic.Dictionary> {
+ { typeof(Whatever.ReferenceVo), new global::System.Lazy(() => new Whatever.ReferenceVo.ReferenceVoSystemTextJsonConverter()) }
+ };
+
+ public override bool CanConvert(global::System.Type typeToConvert) => _lookup.ContainsKey(typeToConvert);
+
+ public override global::System.Text.Json.Serialization.JsonConverter CreateConverter(global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) =>
+ _lookup[typeToConvert].Value;
+}
+
+// ------------------------------------------------------------------------------
+//
+// This code was generated by a source generator named Vogen (https://github.com/SteveDunn/Vogen)
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// ------------------------------------------------------------------------------
+
+// Suppress warnings about [Obsolete] member usage in generated code.
+#pragma warning disable CS0618
+
+// Suppress warnings for 'Override methods on comparable types'.
+#pragma warning disable CA1036
+
+// Suppress Error MA0097 : A class that implements IComparable or IComparable should override comparison operators
+#pragma warning disable MA0097
+
+// Suppress warning for 'The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source.'
+// The generator copies signatures from the BCL, e.g. for `TryParse`, and some of those have nullable annotations.
+#pragma warning disable CS8669
+
+// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
+#pragma warning disable CS1591
+
+using Vogen;
+
+namespace Whatever
+{
+
+ [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Vogen", "1.0.0.0")]
+ [global::System.Text.Json.Serialization.JsonConverter(typeof(ReferenceVoSystemTextJsonConverter))]
+[global::System.ComponentModel.TypeConverter(typeof(ReferenceVoTypeConverter))]
+
+ [global::System.Diagnostics.DebuggerTypeProxyAttribute(typeof(ReferenceVoDebugView))]
+ [global::System.Diagnostics.DebuggerDisplayAttribute("Underlying type: System.Int32, Value = { _value }")]
+ public partial class ReferenceVo : global::System.IEquatable, global::System.IEquatable , global::System.IComparable, global::System.IComparable
+ {
+#if DEBUG
+ private readonly global::System.Diagnostics.StackTrace _stackTrace = null;
+#endif
+ private readonly global::System.Boolean _isInitialized;
+ private readonly System.Int32 _value;
+
+///
+/// Gets the underlying value if set, otherwise a is thrown.
+///
+public System.Int32 Value
+ {
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ get
+ {
+ EnsureInitialized();
+ return _value;
+ }
+ }
+
+
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
+ public ReferenceVo()
+ {
+#if DEBUG
+ _stackTrace = new global::System.Diagnostics.StackTrace();
+#endif
+ _isInitialized = false;
+ _value = default;
+ }
+
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ private ReferenceVo(System.Int32 value)
+ {
+ _value = value;
+ _isInitialized = true;
+ }
+
+ ///
+ /// Builds an instance from the provided underlying type.
+ ///
+ /// The underlying type.
+ /// An instance of this type.
+ public static ReferenceVo From(System.Int32 value)
+ {
+
+
+
+
+
+
+ ReferenceVo instance = new ReferenceVo(value);
+
+ return instance;
+ }
+
+ ///
+/// Tries to build an instance from the provided underlying type.
+/// If a normalization method is provided, it will be called.
+/// If validation is provided, and it fails, false will be returned.
+///
+/// The underlying type.
+/// An instance of the value object.
+/// True if the value object can be built, otherwise false.
+public static bool TryFrom(System.Int32 value,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo vo)
+{
+
+
+
+
+
+ vo = new ReferenceVo(value);
+
+ return true;
+}///
+/// Tries to build an instance from the provided underlying value.
+/// If a normalization method is provided, it will be called.
+/// If validation is provided, and it fails, an error will be returned.
+///
+/// The primitive value.
+/// A containing either the value object, or an error.
+public static ValueObjectOrError TryFrom(System.Int32 value)
+{
+
+
+
+
+
+
+ return new ValueObjectOrError(new ReferenceVo(value));
+}
+
+ public bool IsInitialized() => _isInitialized;
+
+
+
+ // only called internally when something has been deserialized into
+ // its primitive type.
+ private static ReferenceVo __Deserialize(System.Int32 value)
+ {
+
+
+
+
+
+
+ return new ReferenceVo(value);
+ }
+
+ public global::System.Boolean Equals(ReferenceVo other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ // It's possible to create uninitialized instances via converters such as EfCore (HasDefaultValue), which call Equals.
+ // We treat anything uninitialized as not equal to anything, even other uninitialized instances of this type.
+ if(!_isInitialized || !other._isInitialized) return false;
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ return GetType() == other.GetType() && global::System.Collections.Generic.EqualityComparer.Default.Equals(Value, other.Value);
+ }
+ public global::System.Boolean Equals(ReferenceVo other, global::System.Collections.Generic.IEqualityComparer comparer)
+ {
+ return comparer.Equals(this, other);
+ }
+
+
+ public global::System.Boolean Equals(System.Int32 primitive)
+ {
+ return Value.Equals(primitive);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object obj)
+ {
+ return Equals(obj as ReferenceVo);
+ }
+
+ public static global::System.Boolean operator ==(ReferenceVo left, ReferenceVo right) => Equals(left, right);
+ public static global::System.Boolean operator !=(ReferenceVo left, ReferenceVo right) => !Equals(left, right);
+
+ public static global::System.Boolean operator ==(ReferenceVo left, System.Int32 right) => Equals(left.Value, right);
+ public static global::System.Boolean operator !=(ReferenceVo left, System.Int32 right) => !Equals(left.Value, right);
+
+ public static global::System.Boolean operator ==(System.Int32 left, ReferenceVo right) => Equals(left, right.Value);
+ public static global::System.Boolean operator !=(System.Int32 left, ReferenceVo right) => !Equals(left, right.Value);
+
+ public static explicit operator ReferenceVo(System.Int32 value) => From(value);
+ public static explicit operator System.Int32(ReferenceVo value) => value.Value;
+
+ public int CompareTo(ReferenceVo other) => Value.CompareTo(other.Value);
+ public int CompareTo(object other) {
+ if(other is null) return 1;
+ if(other is ReferenceVo x) return CompareTo(x);
+ throw new global::System.ArgumentException("Cannot compare to object as it is not of type ReferenceVo", nameof(other));
+ }
+
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(global::System.ReadOnlySpan s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, style, provider, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(global::System.ReadOnlySpan s,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(string s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, style, provider, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(string s,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(global::System.ReadOnlySpan s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, style, provider);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s) {
+ var r = System.Int32.Parse(s);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.Globalization.NumberStyles style) {
+ var r = System.Int32.Parse(s, style);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, style, provider);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, provider);
+ return From(r);
+ }
+
+
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked // Overflow is fine, just wrap
+ {
+ global::System.Int32 hash = (global::System.Int32) 2166136261;
+ hash = (hash * 16777619) ^ GetType().GetHashCode();
+ hash = (hash * 16777619) ^ global::System.Collections.Generic.EqualityComparer.Default.GetHashCode(Value);
+ return hash;
+ }
+ }
+
+ private void EnsureInitialized()
+ {
+ if (!_isInitialized)
+ {
+#if DEBUG
+ global::System.String message = "Use of uninitialized Value Object at: " + _stackTrace ?? "";
+#else
+ global::System.String message = "Use of uninitialized Value Object.";
+#endif
+
+ throw new global::Vogen.ValueObjectValidationException(message);
+ }
+ }
+
+
+
+
+ /// Returns the string representation of the underlying .
+ public override global::System.String ToString() =>_isInitialized ? Value.ToString() : "[UNINITIALIZED]";
+
+
+ ///
+ /// Converts a ReferenceVo to or from JSON.
+ ///
+ public class ReferenceVoSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter
+ {
+ #if NET5_0_OR_GREATER
+ public override bool HandleNull => true;
+ #endif
+ public override ReferenceVo Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options)
+ {
+#if NET5_0_OR_GREATER
+ return ReferenceVo.__Deserialize(global::System.Text.Json.JsonSerializer.Deserialize(ref reader, (global::System.Text.Json.Serialization.Metadata.JsonTypeInfo)options.GetTypeInfo(typeof(global::System.Int32))));
+#else
+ return ReferenceVo.__Deserialize(reader.GetInt32());
+#endif
+ }
+
+ public override void Write(System.Text.Json.Utf8JsonWriter writer, ReferenceVo value, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ #if NET5_0_OR_GREATER
+ global::System.Text.Json.JsonSerializer.Serialize(writer, value.Value, options);
+ #else
+ writer.WriteNumberValue(value.Value);
+ #endif
+ }
+
+#if NET6_0_OR_GREATER
+ public override ReferenceVo ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ return ReferenceVo.__Deserialize(global::System.Int32.Parse(reader.GetString(), global::System.Globalization.NumberStyles.Any, global::System.Globalization.CultureInfo.InvariantCulture));
+ }
+
+ public override void WriteAsPropertyName(System.Text.Json.Utf8JsonWriter writer, ReferenceVo value, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture));
+ }
+#endif
+ }
+
+
+ class ReferenceVoTypeConverter : global::System.ComponentModel.TypeConverter
+ {
+ public override global::System.Boolean CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType)
+ {
+ return sourceType == typeof(global::System.Int32) || sourceType == typeof(global::System.String) || base.CanConvertFrom(context, sourceType);
+ }
+
+ public override global::System.Object ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, global::System.Object value)
+ {
+ return value switch
+ {
+ global::System.Int32 intValue => ReferenceVo.__Deserialize(intValue),
+ global::System.String stringValue when !global::System.String.IsNullOrEmpty(stringValue) && global::System.Int32.TryParse(stringValue, out var result) => ReferenceVo.__Deserialize(result),
+ _ => base.ConvertFrom(context, culture, value),
+ };
+ }
+
+ public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType)
+ {
+ return sourceType == typeof(global::System.Int32) || sourceType == typeof(global::System.String) || base.CanConvertTo(context, sourceType);
+ }
+
+ public override object ConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, global::System.Object value, global::System.Type destinationType)
+ {
+ if (value is ReferenceVo idValue)
+ {
+ if (destinationType == typeof(global::System.Int32))
+ {
+ return idValue.Value;
+ }
+
+ if (destinationType == typeof(global::System.String))
+ {
+ return idValue.Value.ToString();
+ }
+ }
+
+ return base.ConvertTo(context, culture, value, destinationType);
+ }
+ }
+
+
+
+
+
+ internal sealed class ReferenceVoDebugView
+ {
+ private readonly ReferenceVo _t;
+
+ ReferenceVoDebugView(ReferenceVo t)
+ {
+ _t = t;
+ }
+
+ public global::System.String UnderlyingType => "System.Int32";
+ public System.Int32 Value => _t.Value ;
+
+ public global::System.String Conversions => @"[global::System.Text.Json.Serialization.JsonConverter(typeof(ReferenceVoSystemTextJsonConverter))]
+[global::System.ComponentModel.TypeConverter(typeof(ReferenceVoTypeConverter))]
+";
+ }
+ }
+
+}
+]
\ No newline at end of file
diff --git a/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v3.1/DeserializationStrictnessTests.Reference_value_objects_allow_nulls_by_default.verified.txt b/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v3.1/DeserializationStrictnessTests.Reference_value_objects_allow_nulls_by_default.verified.txt
new file mode 100644
index 0000000000..0fb35503af
--- /dev/null
+++ b/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v3.1/DeserializationStrictnessTests.Reference_value_objects_allow_nulls_by_default.verified.txt
@@ -0,0 +1,532 @@
+[
+// ------------------------------------------------------------------------------
+//
+// This code was generated by a source generator named Vogen (https://github.com/SteveDunn/Vogen)
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// ------------------------------------------------------------------------------
+
+// Suppress warnings about [Obsolete] member usage in generated code.
+#pragma warning disable CS0618
+
+// Suppress warnings for 'Override methods on comparable types'.
+#pragma warning disable CA1036
+
+// Suppress Error MA0097 : A class that implements IComparable or IComparable should override comparison operators
+#pragma warning disable MA0097
+
+// Suppress warning for 'The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source.'
+// The generator copies signatures from the BCL, e.g. for `TryParse`, and some of those have nullable annotations.
+#pragma warning disable CS8669
+
+// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
+#pragma warning disable CS1591
+
+namespace generator;
+
+public class VogenTypesFactory : global::System.Text.Json.Serialization.JsonConverterFactory
+{
+ public VogenTypesFactory() { }
+ private static readonly global::System.Collections.Generic.Dictionary> _lookup =
+ new global::System.Collections.Generic.Dictionary> {
+ { typeof(Whatever.ReferenceVo), new global::System.Lazy(() => new Whatever.ReferenceVo.ReferenceVoSystemTextJsonConverter()) }
+ };
+
+ public override bool CanConvert(global::System.Type typeToConvert) => _lookup.ContainsKey(typeToConvert);
+
+ public override global::System.Text.Json.Serialization.JsonConverter CreateConverter(global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) =>
+ _lookup[typeToConvert].Value;
+}
+
+// ------------------------------------------------------------------------------
+//
+// This code was generated by a source generator named Vogen (https://github.com/SteveDunn/Vogen)
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// ------------------------------------------------------------------------------
+
+// Suppress warnings about [Obsolete] member usage in generated code.
+#pragma warning disable CS0618
+
+// Suppress warnings for 'Override methods on comparable types'.
+#pragma warning disable CA1036
+
+// Suppress Error MA0097 : A class that implements IComparable or IComparable should override comparison operators
+#pragma warning disable MA0097
+
+// Suppress warning for 'The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source.'
+// The generator copies signatures from the BCL, e.g. for `TryParse`, and some of those have nullable annotations.
+#pragma warning disable CS8669
+
+// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
+#pragma warning disable CS1591
+
+using Vogen;
+
+namespace Whatever
+{
+
+ [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Vogen", "1.0.0.0")]
+ [global::System.Text.Json.Serialization.JsonConverter(typeof(ReferenceVoSystemTextJsonConverter))]
+[global::System.ComponentModel.TypeConverter(typeof(ReferenceVoTypeConverter))]
+
+ [global::System.Diagnostics.DebuggerTypeProxyAttribute(typeof(ReferenceVoDebugView))]
+ [global::System.Diagnostics.DebuggerDisplayAttribute("Underlying type: System.Int32, Value = { _value }")]
+ public partial class ReferenceVo : global::System.IEquatable, global::System.IEquatable , global::System.IComparable, global::System.IComparable
+ {
+#if DEBUG
+ private readonly global::System.Diagnostics.StackTrace _stackTrace = null;
+#endif
+ private readonly global::System.Boolean _isInitialized;
+ private readonly System.Int32 _value;
+
+///
+/// Gets the underlying value if set, otherwise a is thrown.
+///
+public System.Int32 Value
+ {
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ get
+ {
+ EnsureInitialized();
+ return _value;
+ }
+ }
+
+
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
+ public ReferenceVo()
+ {
+#if DEBUG
+ _stackTrace = new global::System.Diagnostics.StackTrace();
+#endif
+ _isInitialized = false;
+ _value = default;
+ }
+
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ private ReferenceVo(System.Int32 value)
+ {
+ _value = value;
+ _isInitialized = true;
+ }
+
+ ///
+ /// Builds an instance from the provided underlying type.
+ ///
+ /// The underlying type.
+ /// An instance of this type.
+ public static ReferenceVo From(System.Int32 value)
+ {
+
+
+
+
+
+
+ ReferenceVo instance = new ReferenceVo(value);
+
+ return instance;
+ }
+
+ ///
+/// Tries to build an instance from the provided underlying type.
+/// If a normalization method is provided, it will be called.
+/// If validation is provided, and it fails, false will be returned.
+///
+/// The underlying type.
+/// An instance of the value object.
+/// True if the value object can be built, otherwise false.
+public static bool TryFrom(System.Int32 value,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo vo)
+{
+
+
+
+
+
+ vo = new ReferenceVo(value);
+
+ return true;
+}///
+/// Tries to build an instance from the provided underlying value.
+/// If a normalization method is provided, it will be called.
+/// If validation is provided, and it fails, an error will be returned.
+///
+/// The primitive value.
+/// A containing either the value object, or an error.
+public static ValueObjectOrError TryFrom(System.Int32 value)
+{
+
+
+
+
+
+
+ return new ValueObjectOrError(new ReferenceVo(value));
+}
+
+ public bool IsInitialized() => _isInitialized;
+
+
+
+ // only called internally when something has been deserialized into
+ // its primitive type.
+ private static ReferenceVo __Deserialize(System.Int32 value)
+ {
+
+
+
+
+
+
+ return new ReferenceVo(value);
+ }
+
+ public global::System.Boolean Equals(ReferenceVo other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ // It's possible to create uninitialized instances via converters such as EfCore (HasDefaultValue), which call Equals.
+ // We treat anything uninitialized as not equal to anything, even other uninitialized instances of this type.
+ if(!_isInitialized || !other._isInitialized) return false;
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ return GetType() == other.GetType() && global::System.Collections.Generic.EqualityComparer.Default.Equals(Value, other.Value);
+ }
+ public global::System.Boolean Equals(ReferenceVo other, global::System.Collections.Generic.IEqualityComparer comparer)
+ {
+ return comparer.Equals(this, other);
+ }
+
+
+ public global::System.Boolean Equals(System.Int32 primitive)
+ {
+ return Value.Equals(primitive);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object obj)
+ {
+ return Equals(obj as ReferenceVo);
+ }
+
+ public static global::System.Boolean operator ==(ReferenceVo left, ReferenceVo right) => Equals(left, right);
+ public static global::System.Boolean operator !=(ReferenceVo left, ReferenceVo right) => !Equals(left, right);
+
+ public static global::System.Boolean operator ==(ReferenceVo left, System.Int32 right) => Equals(left.Value, right);
+ public static global::System.Boolean operator !=(ReferenceVo left, System.Int32 right) => !Equals(left.Value, right);
+
+ public static global::System.Boolean operator ==(System.Int32 left, ReferenceVo right) => Equals(left, right.Value);
+ public static global::System.Boolean operator !=(System.Int32 left, ReferenceVo right) => !Equals(left, right.Value);
+
+ public static explicit operator ReferenceVo(System.Int32 value) => From(value);
+ public static explicit operator System.Int32(ReferenceVo value) => value.Value;
+
+ public int CompareTo(ReferenceVo other) => Value.CompareTo(other.Value);
+ public int CompareTo(object other) {
+ if(other is null) return 1;
+ if(other is ReferenceVo x) return CompareTo(x);
+ throw new global::System.ArgumentException("Cannot compare to object as it is not of type ReferenceVo", nameof(other));
+ }
+
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(global::System.ReadOnlySpan s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, style, provider, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(global::System.ReadOnlySpan s,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(string s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, style, provider, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(string s,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(global::System.ReadOnlySpan s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, style, provider);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s) {
+ var r = System.Int32.Parse(s);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.Globalization.NumberStyles style) {
+ var r = System.Int32.Parse(s, style);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, style, provider);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, provider);
+ return From(r);
+ }
+
+
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked // Overflow is fine, just wrap
+ {
+ global::System.Int32 hash = (global::System.Int32) 2166136261;
+ hash = (hash * 16777619) ^ GetType().GetHashCode();
+ hash = (hash * 16777619) ^ global::System.Collections.Generic.EqualityComparer.Default.GetHashCode(Value);
+ return hash;
+ }
+ }
+
+ private void EnsureInitialized()
+ {
+ if (!_isInitialized)
+ {
+#if DEBUG
+ global::System.String message = "Use of uninitialized Value Object at: " + _stackTrace ?? "";
+#else
+ global::System.String message = "Use of uninitialized Value Object.";
+#endif
+
+ throw new global::Vogen.ValueObjectValidationException(message);
+ }
+ }
+
+
+
+
+ /// Returns the string representation of the underlying .
+ public override global::System.String ToString() =>_isInitialized ? Value.ToString() : "[UNINITIALIZED]";
+
+
+ ///
+ /// Converts a ReferenceVo to or from JSON.
+ ///
+ public class ReferenceVoSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter
+ {
+ public override ReferenceVo Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options)
+ {
+#if NET5_0_OR_GREATER
+ return ReferenceVo.__Deserialize(global::System.Text.Json.JsonSerializer.Deserialize(ref reader, (global::System.Text.Json.Serialization.Metadata.JsonTypeInfo)options.GetTypeInfo(typeof(global::System.Int32))));
+#else
+ return ReferenceVo.__Deserialize(reader.GetInt32());
+#endif
+ }
+
+ public override void Write(System.Text.Json.Utf8JsonWriter writer, ReferenceVo value, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ #if NET5_0_OR_GREATER
+ global::System.Text.Json.JsonSerializer.Serialize(writer, value.Value, options);
+ #else
+ writer.WriteNumberValue(value.Value);
+ #endif
+ }
+
+#if NET6_0_OR_GREATER
+ public override ReferenceVo ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ return ReferenceVo.__Deserialize(global::System.Int32.Parse(reader.GetString(), global::System.Globalization.NumberStyles.Any, global::System.Globalization.CultureInfo.InvariantCulture));
+ }
+
+ public override void WriteAsPropertyName(System.Text.Json.Utf8JsonWriter writer, ReferenceVo value, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture));
+ }
+#endif
+ }
+
+
+ class ReferenceVoTypeConverter : global::System.ComponentModel.TypeConverter
+ {
+ public override global::System.Boolean CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType)
+ {
+ return sourceType == typeof(global::System.Int32) || sourceType == typeof(global::System.String) || base.CanConvertFrom(context, sourceType);
+ }
+
+ public override global::System.Object ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, global::System.Object value)
+ {
+ return value switch
+ {
+ global::System.Int32 intValue => ReferenceVo.__Deserialize(intValue),
+ global::System.String stringValue when !global::System.String.IsNullOrEmpty(stringValue) && global::System.Int32.TryParse(stringValue, out var result) => ReferenceVo.__Deserialize(result),
+ _ => base.ConvertFrom(context, culture, value),
+ };
+ }
+
+ public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType)
+ {
+ return sourceType == typeof(global::System.Int32) || sourceType == typeof(global::System.String) || base.CanConvertTo(context, sourceType);
+ }
+
+ public override object ConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, global::System.Object value, global::System.Type destinationType)
+ {
+ if (value is ReferenceVo idValue)
+ {
+ if (destinationType == typeof(global::System.Int32))
+ {
+ return idValue.Value;
+ }
+
+ if (destinationType == typeof(global::System.String))
+ {
+ return idValue.Value.ToString();
+ }
+ }
+
+ return base.ConvertTo(context, culture, value, destinationType);
+ }
+ }
+
+
+
+
+
+ internal sealed class ReferenceVoDebugView
+ {
+ private readonly ReferenceVo _t;
+
+ ReferenceVoDebugView(ReferenceVo t)
+ {
+ _t = t;
+ }
+
+ public global::System.String UnderlyingType => "System.Int32";
+ public System.Int32 Value => _t.Value ;
+
+ public global::System.String Conversions => @"[global::System.Text.Json.Serialization.JsonConverter(typeof(ReferenceVoSystemTextJsonConverter))]
+[global::System.ComponentModel.TypeConverter(typeof(ReferenceVoTypeConverter))]
+";
+ }
+ }
+
+}
+]
\ No newline at end of file
diff --git a/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v4.6.1/DeserializationStrictnessTests.Can_disallow_nulls_for_reference_value_objects.verified.txt b/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v4.6.1/DeserializationStrictnessTests.Can_disallow_nulls_for_reference_value_objects.verified.txt
new file mode 100644
index 0000000000..0244132a42
--- /dev/null
+++ b/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v4.6.1/DeserializationStrictnessTests.Can_disallow_nulls_for_reference_value_objects.verified.txt
@@ -0,0 +1,479 @@
+[
+// ------------------------------------------------------------------------------
+//
+// This code was generated by a source generator named Vogen (https://github.com/SteveDunn/Vogen)
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// ------------------------------------------------------------------------------
+
+// Suppress warnings about [Obsolete] member usage in generated code.
+#pragma warning disable CS0618
+
+// Suppress warnings for 'Override methods on comparable types'.
+#pragma warning disable CA1036
+
+// Suppress Error MA0097 : A class that implements IComparable or IComparable should override comparison operators
+#pragma warning disable MA0097
+
+// Suppress warning for 'The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source.'
+// The generator copies signatures from the BCL, e.g. for `TryParse`, and some of those have nullable annotations.
+#pragma warning disable CS8669
+
+// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
+#pragma warning disable CS1591
+
+namespace generator;
+
+public class VogenTypesFactory : global::System.Text.Json.Serialization.JsonConverterFactory
+{
+ public VogenTypesFactory() { }
+ private static readonly global::System.Collections.Generic.Dictionary> _lookup =
+ new global::System.Collections.Generic.Dictionary> {
+ { typeof(Whatever.ReferenceVo), new global::System.Lazy(() => new Whatever.ReferenceVo.ReferenceVoSystemTextJsonConverter()) }
+ };
+
+ public override bool CanConvert(global::System.Type typeToConvert) => _lookup.ContainsKey(typeToConvert);
+
+ public override global::System.Text.Json.Serialization.JsonConverter CreateConverter(global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) =>
+ _lookup[typeToConvert].Value;
+}
+
+// ------------------------------------------------------------------------------
+//
+// This code was generated by a source generator named Vogen (https://github.com/SteveDunn/Vogen)
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// ------------------------------------------------------------------------------
+
+// Suppress warnings about [Obsolete] member usage in generated code.
+#pragma warning disable CS0618
+
+// Suppress warnings for 'Override methods on comparable types'.
+#pragma warning disable CA1036
+
+// Suppress Error MA0097 : A class that implements IComparable or IComparable should override comparison operators
+#pragma warning disable MA0097
+
+// Suppress warning for 'The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source.'
+// The generator copies signatures from the BCL, e.g. for `TryParse`, and some of those have nullable annotations.
+#pragma warning disable CS8669
+
+// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
+#pragma warning disable CS1591
+
+using Vogen;
+
+namespace Whatever
+{
+
+ [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Vogen", "1.0.0.0")]
+ [global::System.Text.Json.Serialization.JsonConverter(typeof(ReferenceVoSystemTextJsonConverter))]
+[global::System.ComponentModel.TypeConverter(typeof(ReferenceVoTypeConverter))]
+
+ [global::System.Diagnostics.DebuggerTypeProxyAttribute(typeof(ReferenceVoDebugView))]
+ [global::System.Diagnostics.DebuggerDisplayAttribute("Underlying type: System.Int32, Value = { _value }")]
+ public partial class ReferenceVo : global::System.IEquatable, global::System.IEquatable , global::System.IComparable, global::System.IComparable
+ {
+#if DEBUG
+ private readonly global::System.Diagnostics.StackTrace _stackTrace = null;
+#endif
+ private readonly global::System.Boolean _isInitialized;
+ private readonly System.Int32 _value;
+
+///
+/// Gets the underlying value if set, otherwise a is thrown.
+///
+public System.Int32 Value
+ {
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ get
+ {
+ EnsureInitialized();
+ return _value;
+ }
+ }
+
+
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
+ public ReferenceVo()
+ {
+#if DEBUG
+ _stackTrace = new global::System.Diagnostics.StackTrace();
+#endif
+ _isInitialized = false;
+ _value = default;
+ }
+
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ private ReferenceVo(System.Int32 value)
+ {
+ _value = value;
+ _isInitialized = true;
+ }
+
+ ///
+ /// Builds an instance from the provided underlying type.
+ ///
+ /// The underlying type.
+ /// An instance of this type.
+ public static ReferenceVo From(System.Int32 value)
+ {
+
+
+
+
+
+
+ ReferenceVo instance = new ReferenceVo(value);
+
+ return instance;
+ }
+
+ ///
+/// Tries to build an instance from the provided underlying type.
+/// If a normalization method is provided, it will be called.
+/// If validation is provided, and it fails, false will be returned.
+///
+/// The underlying type.
+/// An instance of the value object.
+/// True if the value object can be built, otherwise false.
+public static bool TryFrom(System.Int32 value,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo vo)
+{
+
+
+
+
+
+ vo = new ReferenceVo(value);
+
+ return true;
+}///
+/// Tries to build an instance from the provided underlying value.
+/// If a normalization method is provided, it will be called.
+/// If validation is provided, and it fails, an error will be returned.
+///
+/// The primitive value.
+/// A containing either the value object, or an error.
+public static ValueObjectOrError TryFrom(System.Int32 value)
+{
+
+
+
+
+
+
+ return new ValueObjectOrError(new ReferenceVo(value));
+}
+
+ public bool IsInitialized() => _isInitialized;
+
+
+
+ // only called internally when something has been deserialized into
+ // its primitive type.
+ private static ReferenceVo __Deserialize(System.Int32 value)
+ {
+
+
+
+
+
+
+ return new ReferenceVo(value);
+ }
+
+ public global::System.Boolean Equals(ReferenceVo other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ // It's possible to create uninitialized instances via converters such as EfCore (HasDefaultValue), which call Equals.
+ // We treat anything uninitialized as not equal to anything, even other uninitialized instances of this type.
+ if(!_isInitialized || !other._isInitialized) return false;
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ return GetType() == other.GetType() && global::System.Collections.Generic.EqualityComparer.Default.Equals(Value, other.Value);
+ }
+ public global::System.Boolean Equals(ReferenceVo other, global::System.Collections.Generic.IEqualityComparer comparer)
+ {
+ return comparer.Equals(this, other);
+ }
+
+
+ public global::System.Boolean Equals(System.Int32 primitive)
+ {
+ return Value.Equals(primitive);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object obj)
+ {
+ return Equals(obj as ReferenceVo);
+ }
+
+ public static global::System.Boolean operator ==(ReferenceVo left, ReferenceVo right) => Equals(left, right);
+ public static global::System.Boolean operator !=(ReferenceVo left, ReferenceVo right) => !Equals(left, right);
+
+ public static global::System.Boolean operator ==(ReferenceVo left, System.Int32 right) => Equals(left.Value, right);
+ public static global::System.Boolean operator !=(ReferenceVo left, System.Int32 right) => !Equals(left.Value, right);
+
+ public static global::System.Boolean operator ==(System.Int32 left, ReferenceVo right) => Equals(left, right.Value);
+ public static global::System.Boolean operator !=(System.Int32 left, ReferenceVo right) => !Equals(left, right.Value);
+
+ public static explicit operator ReferenceVo(System.Int32 value) => From(value);
+ public static explicit operator System.Int32(ReferenceVo value) => value.Value;
+
+ public int CompareTo(ReferenceVo other) => Value.CompareTo(other.Value);
+ public int CompareTo(object other) {
+ if(other is null) return 1;
+ if(other is ReferenceVo x) return CompareTo(x);
+ throw new global::System.ArgumentException("Cannot compare to object as it is not of type ReferenceVo", nameof(other));
+ }
+
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(string s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, style, provider, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(string s,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s) {
+ var r = System.Int32.Parse(s);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.Globalization.NumberStyles style) {
+ var r = System.Int32.Parse(s, style);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, style, provider);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, provider);
+ return From(r);
+ }
+
+
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked // Overflow is fine, just wrap
+ {
+ global::System.Int32 hash = (global::System.Int32) 2166136261;
+ hash = (hash * 16777619) ^ GetType().GetHashCode();
+ hash = (hash * 16777619) ^ global::System.Collections.Generic.EqualityComparer.Default.GetHashCode(Value);
+ return hash;
+ }
+ }
+
+ private void EnsureInitialized()
+ {
+ if (!_isInitialized)
+ {
+#if DEBUG
+ global::System.String message = "Use of uninitialized Value Object at: " + _stackTrace ?? "";
+#else
+ global::System.String message = "Use of uninitialized Value Object.";
+#endif
+
+ throw new global::Vogen.ValueObjectValidationException(message);
+ }
+ }
+
+
+
+
+ /// Returns the string representation of the underlying .
+ public override global::System.String ToString() =>_isInitialized ? Value.ToString() : "[UNINITIALIZED]";
+
+
+ ///
+ /// Converts a ReferenceVo to or from JSON.
+ ///
+ public class ReferenceVoSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter
+ {
+ #if NET5_0_OR_GREATER
+ public override bool HandleNull => true;
+ #endif
+ public override ReferenceVo Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options)
+ {
+#if NET5_0_OR_GREATER
+ return ReferenceVo.__Deserialize(global::System.Text.Json.JsonSerializer.Deserialize(ref reader, (global::System.Text.Json.Serialization.Metadata.JsonTypeInfo)options.GetTypeInfo(typeof(global::System.Int32))));
+#else
+ return ReferenceVo.__Deserialize(reader.GetInt32());
+#endif
+ }
+
+ public override void Write(System.Text.Json.Utf8JsonWriter writer, ReferenceVo value, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ #if NET5_0_OR_GREATER
+ global::System.Text.Json.JsonSerializer.Serialize(writer, value.Value, options);
+ #else
+ writer.WriteNumberValue(value.Value);
+ #endif
+ }
+
+#if NET6_0_OR_GREATER
+ public override ReferenceVo ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ return ReferenceVo.__Deserialize(global::System.Int32.Parse(reader.GetString(), global::System.Globalization.NumberStyles.Any, global::System.Globalization.CultureInfo.InvariantCulture));
+ }
+
+ public override void WriteAsPropertyName(System.Text.Json.Utf8JsonWriter writer, ReferenceVo value, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture));
+ }
+#endif
+ }
+
+
+ class ReferenceVoTypeConverter : global::System.ComponentModel.TypeConverter
+ {
+ public override global::System.Boolean CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType)
+ {
+ return sourceType == typeof(global::System.Int32) || sourceType == typeof(global::System.String) || base.CanConvertFrom(context, sourceType);
+ }
+
+ public override global::System.Object ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, global::System.Object value)
+ {
+ return value switch
+ {
+ global::System.Int32 intValue => ReferenceVo.__Deserialize(intValue),
+ global::System.String stringValue when !global::System.String.IsNullOrEmpty(stringValue) && global::System.Int32.TryParse(stringValue, out var result) => ReferenceVo.__Deserialize(result),
+ _ => base.ConvertFrom(context, culture, value),
+ };
+ }
+
+ public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType)
+ {
+ return sourceType == typeof(global::System.Int32) || sourceType == typeof(global::System.String) || base.CanConvertTo(context, sourceType);
+ }
+
+ public override object ConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, global::System.Object value, global::System.Type destinationType)
+ {
+ if (value is ReferenceVo idValue)
+ {
+ if (destinationType == typeof(global::System.Int32))
+ {
+ return idValue.Value;
+ }
+
+ if (destinationType == typeof(global::System.String))
+ {
+ return idValue.Value.ToString();
+ }
+ }
+
+ return base.ConvertTo(context, culture, value, destinationType);
+ }
+ }
+
+
+
+
+
+ internal sealed class ReferenceVoDebugView
+ {
+ private readonly ReferenceVo _t;
+
+ ReferenceVoDebugView(ReferenceVo t)
+ {
+ _t = t;
+ }
+
+ public global::System.String UnderlyingType => "System.Int32";
+ public System.Int32 Value => _t.Value ;
+
+ public global::System.String Conversions => @"[global::System.Text.Json.Serialization.JsonConverter(typeof(ReferenceVoSystemTextJsonConverter))]
+[global::System.ComponentModel.TypeConverter(typeof(ReferenceVoTypeConverter))]
+";
+ }
+ }
+
+}
+]
\ No newline at end of file
diff --git a/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v4.6.1/DeserializationStrictnessTests.Reference_value_objects_allow_nulls_by_default.verified.txt b/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v4.6.1/DeserializationStrictnessTests.Reference_value_objects_allow_nulls_by_default.verified.txt
new file mode 100644
index 0000000000..0719647f77
--- /dev/null
+++ b/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v4.6.1/DeserializationStrictnessTests.Reference_value_objects_allow_nulls_by_default.verified.txt
@@ -0,0 +1,476 @@
+[
+// ------------------------------------------------------------------------------
+//
+// This code was generated by a source generator named Vogen (https://github.com/SteveDunn/Vogen)
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// ------------------------------------------------------------------------------
+
+// Suppress warnings about [Obsolete] member usage in generated code.
+#pragma warning disable CS0618
+
+// Suppress warnings for 'Override methods on comparable types'.
+#pragma warning disable CA1036
+
+// Suppress Error MA0097 : A class that implements IComparable or IComparable should override comparison operators
+#pragma warning disable MA0097
+
+// Suppress warning for 'The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source.'
+// The generator copies signatures from the BCL, e.g. for `TryParse`, and some of those have nullable annotations.
+#pragma warning disable CS8669
+
+// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
+#pragma warning disable CS1591
+
+namespace generator;
+
+public class VogenTypesFactory : global::System.Text.Json.Serialization.JsonConverterFactory
+{
+ public VogenTypesFactory() { }
+ private static readonly global::System.Collections.Generic.Dictionary> _lookup =
+ new global::System.Collections.Generic.Dictionary> {
+ { typeof(Whatever.ReferenceVo), new global::System.Lazy(() => new Whatever.ReferenceVo.ReferenceVoSystemTextJsonConverter()) }
+ };
+
+ public override bool CanConvert(global::System.Type typeToConvert) => _lookup.ContainsKey(typeToConvert);
+
+ public override global::System.Text.Json.Serialization.JsonConverter CreateConverter(global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) =>
+ _lookup[typeToConvert].Value;
+}
+
+// ------------------------------------------------------------------------------
+//
+// This code was generated by a source generator named Vogen (https://github.com/SteveDunn/Vogen)
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// ------------------------------------------------------------------------------
+
+// Suppress warnings about [Obsolete] member usage in generated code.
+#pragma warning disable CS0618
+
+// Suppress warnings for 'Override methods on comparable types'.
+#pragma warning disable CA1036
+
+// Suppress Error MA0097 : A class that implements IComparable or IComparable should override comparison operators
+#pragma warning disable MA0097
+
+// Suppress warning for 'The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source.'
+// The generator copies signatures from the BCL, e.g. for `TryParse`, and some of those have nullable annotations.
+#pragma warning disable CS8669
+
+// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
+#pragma warning disable CS1591
+
+using Vogen;
+
+namespace Whatever
+{
+
+ [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Vogen", "1.0.0.0")]
+ [global::System.Text.Json.Serialization.JsonConverter(typeof(ReferenceVoSystemTextJsonConverter))]
+[global::System.ComponentModel.TypeConverter(typeof(ReferenceVoTypeConverter))]
+
+ [global::System.Diagnostics.DebuggerTypeProxyAttribute(typeof(ReferenceVoDebugView))]
+ [global::System.Diagnostics.DebuggerDisplayAttribute("Underlying type: System.Int32, Value = { _value }")]
+ public partial class ReferenceVo : global::System.IEquatable, global::System.IEquatable , global::System.IComparable, global::System.IComparable
+ {
+#if DEBUG
+ private readonly global::System.Diagnostics.StackTrace _stackTrace = null;
+#endif
+ private readonly global::System.Boolean _isInitialized;
+ private readonly System.Int32 _value;
+
+///
+/// Gets the underlying value if set, otherwise a is thrown.
+///
+public System.Int32 Value
+ {
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ get
+ {
+ EnsureInitialized();
+ return _value;
+ }
+ }
+
+
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
+ public ReferenceVo()
+ {
+#if DEBUG
+ _stackTrace = new global::System.Diagnostics.StackTrace();
+#endif
+ _isInitialized = false;
+ _value = default;
+ }
+
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ private ReferenceVo(System.Int32 value)
+ {
+ _value = value;
+ _isInitialized = true;
+ }
+
+ ///
+ /// Builds an instance from the provided underlying type.
+ ///
+ /// The underlying type.
+ /// An instance of this type.
+ public static ReferenceVo From(System.Int32 value)
+ {
+
+
+
+
+
+
+ ReferenceVo instance = new ReferenceVo(value);
+
+ return instance;
+ }
+
+ ///
+/// Tries to build an instance from the provided underlying type.
+/// If a normalization method is provided, it will be called.
+/// If validation is provided, and it fails, false will be returned.
+///
+/// The underlying type.
+/// An instance of the value object.
+/// True if the value object can be built, otherwise false.
+public static bool TryFrom(System.Int32 value,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo vo)
+{
+
+
+
+
+
+ vo = new ReferenceVo(value);
+
+ return true;
+}///
+/// Tries to build an instance from the provided underlying value.
+/// If a normalization method is provided, it will be called.
+/// If validation is provided, and it fails, an error will be returned.
+///
+/// The primitive value.
+/// A containing either the value object, or an error.
+public static ValueObjectOrError TryFrom(System.Int32 value)
+{
+
+
+
+
+
+
+ return new ValueObjectOrError(new ReferenceVo(value));
+}
+
+ public bool IsInitialized() => _isInitialized;
+
+
+
+ // only called internally when something has been deserialized into
+ // its primitive type.
+ private static ReferenceVo __Deserialize(System.Int32 value)
+ {
+
+
+
+
+
+
+ return new ReferenceVo(value);
+ }
+
+ public global::System.Boolean Equals(ReferenceVo other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ // It's possible to create uninitialized instances via converters such as EfCore (HasDefaultValue), which call Equals.
+ // We treat anything uninitialized as not equal to anything, even other uninitialized instances of this type.
+ if(!_isInitialized || !other._isInitialized) return false;
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ return GetType() == other.GetType() && global::System.Collections.Generic.EqualityComparer.Default.Equals(Value, other.Value);
+ }
+ public global::System.Boolean Equals(ReferenceVo other, global::System.Collections.Generic.IEqualityComparer comparer)
+ {
+ return comparer.Equals(this, other);
+ }
+
+
+ public global::System.Boolean Equals(System.Int32 primitive)
+ {
+ return Value.Equals(primitive);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object obj)
+ {
+ return Equals(obj as ReferenceVo);
+ }
+
+ public static global::System.Boolean operator ==(ReferenceVo left, ReferenceVo right) => Equals(left, right);
+ public static global::System.Boolean operator !=(ReferenceVo left, ReferenceVo right) => !Equals(left, right);
+
+ public static global::System.Boolean operator ==(ReferenceVo left, System.Int32 right) => Equals(left.Value, right);
+ public static global::System.Boolean operator !=(ReferenceVo left, System.Int32 right) => !Equals(left.Value, right);
+
+ public static global::System.Boolean operator ==(System.Int32 left, ReferenceVo right) => Equals(left, right.Value);
+ public static global::System.Boolean operator !=(System.Int32 left, ReferenceVo right) => !Equals(left, right.Value);
+
+ public static explicit operator ReferenceVo(System.Int32 value) => From(value);
+ public static explicit operator System.Int32(ReferenceVo value) => value.Value;
+
+ public int CompareTo(ReferenceVo other) => Value.CompareTo(other.Value);
+ public int CompareTo(object other) {
+ if(other is null) return 1;
+ if(other is ReferenceVo x) return CompareTo(x);
+ throw new global::System.ArgumentException("Cannot compare to object as it is not of type ReferenceVo", nameof(other));
+ }
+
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(string s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, style, provider, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(string s,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s) {
+ var r = System.Int32.Parse(s);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.Globalization.NumberStyles style) {
+ var r = System.Int32.Parse(s, style);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, style, provider);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, provider);
+ return From(r);
+ }
+
+
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked // Overflow is fine, just wrap
+ {
+ global::System.Int32 hash = (global::System.Int32) 2166136261;
+ hash = (hash * 16777619) ^ GetType().GetHashCode();
+ hash = (hash * 16777619) ^ global::System.Collections.Generic.EqualityComparer.Default.GetHashCode(Value);
+ return hash;
+ }
+ }
+
+ private void EnsureInitialized()
+ {
+ if (!_isInitialized)
+ {
+#if DEBUG
+ global::System.String message = "Use of uninitialized Value Object at: " + _stackTrace ?? "";
+#else
+ global::System.String message = "Use of uninitialized Value Object.";
+#endif
+
+ throw new global::Vogen.ValueObjectValidationException(message);
+ }
+ }
+
+
+
+
+ /// Returns the string representation of the underlying .
+ public override global::System.String ToString() =>_isInitialized ? Value.ToString() : "[UNINITIALIZED]";
+
+
+ ///
+ /// Converts a ReferenceVo to or from JSON.
+ ///
+ public class ReferenceVoSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter
+ {
+ public override ReferenceVo Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options)
+ {
+#if NET5_0_OR_GREATER
+ return ReferenceVo.__Deserialize(global::System.Text.Json.JsonSerializer.Deserialize(ref reader, (global::System.Text.Json.Serialization.Metadata.JsonTypeInfo)options.GetTypeInfo(typeof(global::System.Int32))));
+#else
+ return ReferenceVo.__Deserialize(reader.GetInt32());
+#endif
+ }
+
+ public override void Write(System.Text.Json.Utf8JsonWriter writer, ReferenceVo value, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ #if NET5_0_OR_GREATER
+ global::System.Text.Json.JsonSerializer.Serialize(writer, value.Value, options);
+ #else
+ writer.WriteNumberValue(value.Value);
+ #endif
+ }
+
+#if NET6_0_OR_GREATER
+ public override ReferenceVo ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ return ReferenceVo.__Deserialize(global::System.Int32.Parse(reader.GetString(), global::System.Globalization.NumberStyles.Any, global::System.Globalization.CultureInfo.InvariantCulture));
+ }
+
+ public override void WriteAsPropertyName(System.Text.Json.Utf8JsonWriter writer, ReferenceVo value, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture));
+ }
+#endif
+ }
+
+
+ class ReferenceVoTypeConverter : global::System.ComponentModel.TypeConverter
+ {
+ public override global::System.Boolean CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType)
+ {
+ return sourceType == typeof(global::System.Int32) || sourceType == typeof(global::System.String) || base.CanConvertFrom(context, sourceType);
+ }
+
+ public override global::System.Object ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, global::System.Object value)
+ {
+ return value switch
+ {
+ global::System.Int32 intValue => ReferenceVo.__Deserialize(intValue),
+ global::System.String stringValue when !global::System.String.IsNullOrEmpty(stringValue) && global::System.Int32.TryParse(stringValue, out var result) => ReferenceVo.__Deserialize(result),
+ _ => base.ConvertFrom(context, culture, value),
+ };
+ }
+
+ public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType)
+ {
+ return sourceType == typeof(global::System.Int32) || sourceType == typeof(global::System.String) || base.CanConvertTo(context, sourceType);
+ }
+
+ public override object ConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, global::System.Object value, global::System.Type destinationType)
+ {
+ if (value is ReferenceVo idValue)
+ {
+ if (destinationType == typeof(global::System.Int32))
+ {
+ return idValue.Value;
+ }
+
+ if (destinationType == typeof(global::System.String))
+ {
+ return idValue.Value.ToString();
+ }
+ }
+
+ return base.ConvertTo(context, culture, value, destinationType);
+ }
+ }
+
+
+
+
+
+ internal sealed class ReferenceVoDebugView
+ {
+ private readonly ReferenceVo _t;
+
+ ReferenceVoDebugView(ReferenceVo t)
+ {
+ _t = t;
+ }
+
+ public global::System.String UnderlyingType => "System.Int32";
+ public System.Int32 Value => _t.Value ;
+
+ public global::System.String Conversions => @"[global::System.Text.Json.Serialization.JsonConverter(typeof(ReferenceVoSystemTextJsonConverter))]
+[global::System.ComponentModel.TypeConverter(typeof(ReferenceVoTypeConverter))]
+";
+ }
+ }
+
+}
+]
\ No newline at end of file
diff --git a/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v4.8/DeserializationStrictnessTests.Can_disallow_nulls_for_reference_value_objects.verified.txt b/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v4.8/DeserializationStrictnessTests.Can_disallow_nulls_for_reference_value_objects.verified.txt
new file mode 100644
index 0000000000..670e6b0b5e
--- /dev/null
+++ b/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v4.8/DeserializationStrictnessTests.Can_disallow_nulls_for_reference_value_objects.verified.txt
@@ -0,0 +1,479 @@
+[
+// ------------------------------------------------------------------------------
+//
+// This code was generated by a source generator named Vogen (https://github.com/SteveDunn/Vogen)
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// ------------------------------------------------------------------------------
+
+// Suppress warnings about [Obsolete] member usage in generated code.
+#pragma warning disable CS0618
+
+// Suppress warnings for 'Override methods on comparable types'.
+#pragma warning disable CA1036
+
+// Suppress Error MA0097 : A class that implements IComparable or IComparable should override comparison operators
+#pragma warning disable MA0097
+
+// Suppress warning for 'The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source.'
+// The generator copies signatures from the BCL, e.g. for `TryParse`, and some of those have nullable annotations.
+#pragma warning disable CS8669
+
+// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
+#pragma warning disable CS1591
+
+namespace generator;
+
+public class VogenTypesFactory : global::System.Text.Json.Serialization.JsonConverterFactory
+{
+ public VogenTypesFactory() { }
+ private static readonly global::System.Collections.Generic.Dictionary> _lookup =
+ new global::System.Collections.Generic.Dictionary> {
+ { typeof(Whatever.ReferenceVo), new global::System.Lazy(() => new Whatever.ReferenceVo.ReferenceVoSystemTextJsonConverter()) }
+ };
+
+ public override bool CanConvert(global::System.Type typeToConvert) => _lookup.ContainsKey(typeToConvert);
+
+ public override global::System.Text.Json.Serialization.JsonConverter CreateConverter(global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) =>
+ _lookup[typeToConvert].Value;
+}
+
+// ------------------------------------------------------------------------------
+//
+// This code was generated by a source generator named Vogen (https://github.com/SteveDunn/Vogen)
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// ------------------------------------------------------------------------------
+
+// Suppress warnings about [Obsolete] member usage in generated code.
+#pragma warning disable CS0618
+
+// Suppress warnings for 'Override methods on comparable types'.
+#pragma warning disable CA1036
+
+// Suppress Error MA0097 : A class that implements IComparable or IComparable should override comparison operators
+#pragma warning disable MA0097
+
+// Suppress warning for 'The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source.'
+// The generator copies signatures from the BCL, e.g. for `TryParse`, and some of those have nullable annotations.
+#pragma warning disable CS8669
+
+// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
+#pragma warning disable CS1591
+
+using Vogen;
+
+namespace Whatever
+{
+
+ [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Vogen", "1.0.0.0")]
+ [global::System.Text.Json.Serialization.JsonConverter(typeof(ReferenceVoSystemTextJsonConverter))]
+[global::System.ComponentModel.TypeConverter(typeof(ReferenceVoTypeConverter))]
+
+ [global::System.Diagnostics.DebuggerTypeProxyAttribute(typeof(ReferenceVoDebugView))]
+ [global::System.Diagnostics.DebuggerDisplayAttribute("Underlying type: System.Int32, Value = { _value }")]
+ public partial class ReferenceVo : global::System.IEquatable, global::System.IEquatable , global::System.IComparable, global::System.IComparable
+ {
+#if DEBUG
+ private readonly global::System.Diagnostics.StackTrace _stackTrace = null;
+#endif
+ private readonly global::System.Boolean _isInitialized;
+ private readonly System.Int32 _value;
+
+///
+/// Gets the underlying value if set, otherwise a is thrown.
+///
+public System.Int32 Value
+ {
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ get
+ {
+ EnsureInitialized();
+ return _value;
+ }
+ }
+
+
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
+ public ReferenceVo()
+ {
+#if DEBUG
+ _stackTrace = new global::System.Diagnostics.StackTrace();
+#endif
+ _isInitialized = false;
+ _value = default;
+ }
+
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ private ReferenceVo(System.Int32 value)
+ {
+ _value = value;
+ _isInitialized = true;
+ }
+
+ ///
+ /// Builds an instance from the provided underlying type.
+ ///
+ /// The underlying type.
+ /// An instance of this type.
+ public static ReferenceVo From(System.Int32 value)
+ {
+
+
+
+
+
+
+ ReferenceVo instance = new ReferenceVo(value);
+
+ return instance;
+ }
+
+ ///
+/// Tries to build an instance from the provided underlying type.
+/// If a normalization method is provided, it will be called.
+/// If validation is provided, and it fails, false will be returned.
+///
+/// The underlying type.
+/// An instance of the value object.
+/// True if the value object can be built, otherwise false.
+public static bool TryFrom(System.Int32 value,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo vo)
+{
+
+
+
+
+
+ vo = new ReferenceVo(value);
+
+ return true;
+}///
+/// Tries to build an instance from the provided underlying value.
+/// If a normalization method is provided, it will be called.
+/// If validation is provided, and it fails, an error will be returned.
+///
+/// The primitive value.
+/// A containing either the value object, or an error.
+public static ValueObjectOrError TryFrom(System.Int32 value)
+{
+
+
+
+
+
+
+ return new ValueObjectOrError(new ReferenceVo(value));
+}
+
+ public bool IsInitialized() => _isInitialized;
+
+
+
+ // only called internally when something has been deserialized into
+ // its primitive type.
+ private static ReferenceVo __Deserialize(System.Int32 value)
+ {
+
+
+
+
+
+
+ return new ReferenceVo(value);
+ }
+
+ public global::System.Boolean Equals(ReferenceVo other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ // It's possible to create uninitialized instances via converters such as EfCore (HasDefaultValue), which call Equals.
+ // We treat anything uninitialized as not equal to anything, even other uninitialized instances of this type.
+ if(!_isInitialized || !other._isInitialized) return false;
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ return GetType() == other.GetType() && global::System.Collections.Generic.EqualityComparer.Default.Equals(Value, other.Value);
+ }
+ public global::System.Boolean Equals(ReferenceVo other, global::System.Collections.Generic.IEqualityComparer comparer)
+ {
+ return comparer.Equals(this, other);
+ }
+
+
+ public global::System.Boolean Equals(System.Int32 primitive)
+ {
+ return Value.Equals(primitive);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object obj)
+ {
+ return Equals(obj as ReferenceVo);
+ }
+
+ public static global::System.Boolean operator ==(ReferenceVo left, ReferenceVo right) => Equals(left, right);
+ public static global::System.Boolean operator !=(ReferenceVo left, ReferenceVo right) => !Equals(left, right);
+
+ public static global::System.Boolean operator ==(ReferenceVo left, System.Int32 right) => Equals(left.Value, right);
+ public static global::System.Boolean operator !=(ReferenceVo left, System.Int32 right) => !Equals(left.Value, right);
+
+ public static global::System.Boolean operator ==(System.Int32 left, ReferenceVo right) => Equals(left, right.Value);
+ public static global::System.Boolean operator !=(System.Int32 left, ReferenceVo right) => !Equals(left, right.Value);
+
+ public static explicit operator ReferenceVo(System.Int32 value) => From(value);
+ public static explicit operator System.Int32(ReferenceVo value) => value.Value;
+
+ public int CompareTo(ReferenceVo other) => Value.CompareTo(other.Value);
+ public int CompareTo(object other) {
+ if(other is null) return 1;
+ if(other is ReferenceVo x) return CompareTo(x);
+ throw new global::System.ArgumentException("Cannot compare to object as it is not of type ReferenceVo", nameof(other));
+ }
+
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(string s,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(string s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, style, provider, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s) {
+ var r = System.Int32.Parse(s);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.Globalization.NumberStyles style) {
+ var r = System.Int32.Parse(s, style);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, provider);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, style, provider);
+ return From(r);
+ }
+
+
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked // Overflow is fine, just wrap
+ {
+ global::System.Int32 hash = (global::System.Int32) 2166136261;
+ hash = (hash * 16777619) ^ GetType().GetHashCode();
+ hash = (hash * 16777619) ^ global::System.Collections.Generic.EqualityComparer.Default.GetHashCode(Value);
+ return hash;
+ }
+ }
+
+ private void EnsureInitialized()
+ {
+ if (!_isInitialized)
+ {
+#if DEBUG
+ global::System.String message = "Use of uninitialized Value Object at: " + _stackTrace ?? "";
+#else
+ global::System.String message = "Use of uninitialized Value Object.";
+#endif
+
+ throw new global::Vogen.ValueObjectValidationException(message);
+ }
+ }
+
+
+
+
+ /// Returns the string representation of the underlying .
+ public override global::System.String ToString() =>_isInitialized ? Value.ToString() : "[UNINITIALIZED]";
+
+
+ ///
+ /// Converts a ReferenceVo to or from JSON.
+ ///
+ public class ReferenceVoSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter
+ {
+ #if NET5_0_OR_GREATER
+ public override bool HandleNull => true;
+ #endif
+ public override ReferenceVo Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options)
+ {
+#if NET5_0_OR_GREATER
+ return ReferenceVo.__Deserialize(global::System.Text.Json.JsonSerializer.Deserialize(ref reader, (global::System.Text.Json.Serialization.Metadata.JsonTypeInfo)options.GetTypeInfo(typeof(global::System.Int32))));
+#else
+ return ReferenceVo.__Deserialize(reader.GetInt32());
+#endif
+ }
+
+ public override void Write(System.Text.Json.Utf8JsonWriter writer, ReferenceVo value, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ #if NET5_0_OR_GREATER
+ global::System.Text.Json.JsonSerializer.Serialize(writer, value.Value, options);
+ #else
+ writer.WriteNumberValue(value.Value);
+ #endif
+ }
+
+#if NET6_0_OR_GREATER
+ public override ReferenceVo ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ return ReferenceVo.__Deserialize(global::System.Int32.Parse(reader.GetString(), global::System.Globalization.NumberStyles.Any, global::System.Globalization.CultureInfo.InvariantCulture));
+ }
+
+ public override void WriteAsPropertyName(System.Text.Json.Utf8JsonWriter writer, ReferenceVo value, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture));
+ }
+#endif
+ }
+
+
+ class ReferenceVoTypeConverter : global::System.ComponentModel.TypeConverter
+ {
+ public override global::System.Boolean CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType)
+ {
+ return sourceType == typeof(global::System.Int32) || sourceType == typeof(global::System.String) || base.CanConvertFrom(context, sourceType);
+ }
+
+ public override global::System.Object ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, global::System.Object value)
+ {
+ return value switch
+ {
+ global::System.Int32 intValue => ReferenceVo.__Deserialize(intValue),
+ global::System.String stringValue when !global::System.String.IsNullOrEmpty(stringValue) && global::System.Int32.TryParse(stringValue, out var result) => ReferenceVo.__Deserialize(result),
+ _ => base.ConvertFrom(context, culture, value),
+ };
+ }
+
+ public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType)
+ {
+ return sourceType == typeof(global::System.Int32) || sourceType == typeof(global::System.String) || base.CanConvertTo(context, sourceType);
+ }
+
+ public override object ConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, global::System.Object value, global::System.Type destinationType)
+ {
+ if (value is ReferenceVo idValue)
+ {
+ if (destinationType == typeof(global::System.Int32))
+ {
+ return idValue.Value;
+ }
+
+ if (destinationType == typeof(global::System.String))
+ {
+ return idValue.Value.ToString();
+ }
+ }
+
+ return base.ConvertTo(context, culture, value, destinationType);
+ }
+ }
+
+
+
+
+
+ internal sealed class ReferenceVoDebugView
+ {
+ private readonly ReferenceVo _t;
+
+ ReferenceVoDebugView(ReferenceVo t)
+ {
+ _t = t;
+ }
+
+ public global::System.String UnderlyingType => "System.Int32";
+ public System.Int32 Value => _t.Value ;
+
+ public global::System.String Conversions => @"[global::System.Text.Json.Serialization.JsonConverter(typeof(ReferenceVoSystemTextJsonConverter))]
+[global::System.ComponentModel.TypeConverter(typeof(ReferenceVoTypeConverter))]
+";
+ }
+ }
+
+}
+]
\ No newline at end of file
diff --git a/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v4.8/DeserializationStrictnessTests.Reference_value_objects_allow_nulls_by_default.verified.txt b/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v4.8/DeserializationStrictnessTests.Reference_value_objects_allow_nulls_by_default.verified.txt
new file mode 100644
index 0000000000..2a5f34987d
--- /dev/null
+++ b/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v4.8/DeserializationStrictnessTests.Reference_value_objects_allow_nulls_by_default.verified.txt
@@ -0,0 +1,476 @@
+[
+// ------------------------------------------------------------------------------
+//
+// This code was generated by a source generator named Vogen (https://github.com/SteveDunn/Vogen)
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// ------------------------------------------------------------------------------
+
+// Suppress warnings about [Obsolete] member usage in generated code.
+#pragma warning disable CS0618
+
+// Suppress warnings for 'Override methods on comparable types'.
+#pragma warning disable CA1036
+
+// Suppress Error MA0097 : A class that implements IComparable or IComparable should override comparison operators
+#pragma warning disable MA0097
+
+// Suppress warning for 'The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source.'
+// The generator copies signatures from the BCL, e.g. for `TryParse`, and some of those have nullable annotations.
+#pragma warning disable CS8669
+
+// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
+#pragma warning disable CS1591
+
+namespace generator;
+
+public class VogenTypesFactory : global::System.Text.Json.Serialization.JsonConverterFactory
+{
+ public VogenTypesFactory() { }
+ private static readonly global::System.Collections.Generic.Dictionary> _lookup =
+ new global::System.Collections.Generic.Dictionary> {
+ { typeof(Whatever.ReferenceVo), new global::System.Lazy(() => new Whatever.ReferenceVo.ReferenceVoSystemTextJsonConverter()) }
+ };
+
+ public override bool CanConvert(global::System.Type typeToConvert) => _lookup.ContainsKey(typeToConvert);
+
+ public override global::System.Text.Json.Serialization.JsonConverter CreateConverter(global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) =>
+ _lookup[typeToConvert].Value;
+}
+
+// ------------------------------------------------------------------------------
+//
+// This code was generated by a source generator named Vogen (https://github.com/SteveDunn/Vogen)
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// ------------------------------------------------------------------------------
+
+// Suppress warnings about [Obsolete] member usage in generated code.
+#pragma warning disable CS0618
+
+// Suppress warnings for 'Override methods on comparable types'.
+#pragma warning disable CA1036
+
+// Suppress Error MA0097 : A class that implements IComparable or IComparable should override comparison operators
+#pragma warning disable MA0097
+
+// Suppress warning for 'The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source.'
+// The generator copies signatures from the BCL, e.g. for `TryParse`, and some of those have nullable annotations.
+#pragma warning disable CS8669
+
+// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
+#pragma warning disable CS1591
+
+using Vogen;
+
+namespace Whatever
+{
+
+ [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Vogen", "1.0.0.0")]
+ [global::System.Text.Json.Serialization.JsonConverter(typeof(ReferenceVoSystemTextJsonConverter))]
+[global::System.ComponentModel.TypeConverter(typeof(ReferenceVoTypeConverter))]
+
+ [global::System.Diagnostics.DebuggerTypeProxyAttribute(typeof(ReferenceVoDebugView))]
+ [global::System.Diagnostics.DebuggerDisplayAttribute("Underlying type: System.Int32, Value = { _value }")]
+ public partial class ReferenceVo : global::System.IEquatable, global::System.IEquatable , global::System.IComparable, global::System.IComparable
+ {
+#if DEBUG
+ private readonly global::System.Diagnostics.StackTrace _stackTrace = null;
+#endif
+ private readonly global::System.Boolean _isInitialized;
+ private readonly System.Int32 _value;
+
+///
+/// Gets the underlying value if set, otherwise a is thrown.
+///
+public System.Int32 Value
+ {
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ get
+ {
+ EnsureInitialized();
+ return _value;
+ }
+ }
+
+
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
+ public ReferenceVo()
+ {
+#if DEBUG
+ _stackTrace = new global::System.Diagnostics.StackTrace();
+#endif
+ _isInitialized = false;
+ _value = default;
+ }
+
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ private ReferenceVo(System.Int32 value)
+ {
+ _value = value;
+ _isInitialized = true;
+ }
+
+ ///
+ /// Builds an instance from the provided underlying type.
+ ///
+ /// The underlying type.
+ /// An instance of this type.
+ public static ReferenceVo From(System.Int32 value)
+ {
+
+
+
+
+
+
+ ReferenceVo instance = new ReferenceVo(value);
+
+ return instance;
+ }
+
+ ///
+/// Tries to build an instance from the provided underlying type.
+/// If a normalization method is provided, it will be called.
+/// If validation is provided, and it fails, false will be returned.
+///
+/// The underlying type.
+/// An instance of the value object.
+/// True if the value object can be built, otherwise false.
+public static bool TryFrom(System.Int32 value,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo vo)
+{
+
+
+
+
+
+ vo = new ReferenceVo(value);
+
+ return true;
+}///
+/// Tries to build an instance from the provided underlying value.
+/// If a normalization method is provided, it will be called.
+/// If validation is provided, and it fails, an error will be returned.
+///
+/// The primitive value.
+/// A containing either the value object, or an error.
+public static ValueObjectOrError TryFrom(System.Int32 value)
+{
+
+
+
+
+
+
+ return new ValueObjectOrError(new ReferenceVo(value));
+}
+
+ public bool IsInitialized() => _isInitialized;
+
+
+
+ // only called internally when something has been deserialized into
+ // its primitive type.
+ private static ReferenceVo __Deserialize(System.Int32 value)
+ {
+
+
+
+
+
+
+ return new ReferenceVo(value);
+ }
+
+ public global::System.Boolean Equals(ReferenceVo other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ // It's possible to create uninitialized instances via converters such as EfCore (HasDefaultValue), which call Equals.
+ // We treat anything uninitialized as not equal to anything, even other uninitialized instances of this type.
+ if(!_isInitialized || !other._isInitialized) return false;
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ return GetType() == other.GetType() && global::System.Collections.Generic.EqualityComparer.Default.Equals(Value, other.Value);
+ }
+ public global::System.Boolean Equals(ReferenceVo other, global::System.Collections.Generic.IEqualityComparer comparer)
+ {
+ return comparer.Equals(this, other);
+ }
+
+
+ public global::System.Boolean Equals(System.Int32 primitive)
+ {
+ return Value.Equals(primitive);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object obj)
+ {
+ return Equals(obj as ReferenceVo);
+ }
+
+ public static global::System.Boolean operator ==(ReferenceVo left, ReferenceVo right) => Equals(left, right);
+ public static global::System.Boolean operator !=(ReferenceVo left, ReferenceVo right) => !Equals(left, right);
+
+ public static global::System.Boolean operator ==(ReferenceVo left, System.Int32 right) => Equals(left.Value, right);
+ public static global::System.Boolean operator !=(ReferenceVo left, System.Int32 right) => !Equals(left.Value, right);
+
+ public static global::System.Boolean operator ==(System.Int32 left, ReferenceVo right) => Equals(left, right.Value);
+ public static global::System.Boolean operator !=(System.Int32 left, ReferenceVo right) => !Equals(left, right.Value);
+
+ public static explicit operator ReferenceVo(System.Int32 value) => From(value);
+ public static explicit operator System.Int32(ReferenceVo value) => value.Value;
+
+ public int CompareTo(ReferenceVo other) => Value.CompareTo(other.Value);
+ public int CompareTo(object other) {
+ if(other is null) return 1;
+ if(other is ReferenceVo x) return CompareTo(x);
+ throw new global::System.ArgumentException("Cannot compare to object as it is not of type ReferenceVo", nameof(other));
+ }
+
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(string s,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(string s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, style, provider, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s) {
+ var r = System.Int32.Parse(s);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.Globalization.NumberStyles style) {
+ var r = System.Int32.Parse(s, style);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, provider);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, style, provider);
+ return From(r);
+ }
+
+
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked // Overflow is fine, just wrap
+ {
+ global::System.Int32 hash = (global::System.Int32) 2166136261;
+ hash = (hash * 16777619) ^ GetType().GetHashCode();
+ hash = (hash * 16777619) ^ global::System.Collections.Generic.EqualityComparer.Default.GetHashCode(Value);
+ return hash;
+ }
+ }
+
+ private void EnsureInitialized()
+ {
+ if (!_isInitialized)
+ {
+#if DEBUG
+ global::System.String message = "Use of uninitialized Value Object at: " + _stackTrace ?? "";
+#else
+ global::System.String message = "Use of uninitialized Value Object.";
+#endif
+
+ throw new global::Vogen.ValueObjectValidationException(message);
+ }
+ }
+
+
+
+
+ /// Returns the string representation of the underlying .
+ public override global::System.String ToString() =>_isInitialized ? Value.ToString() : "[UNINITIALIZED]";
+
+
+ ///
+ /// Converts a ReferenceVo to or from JSON.
+ ///
+ public class ReferenceVoSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter
+ {
+ public override ReferenceVo Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options)
+ {
+#if NET5_0_OR_GREATER
+ return ReferenceVo.__Deserialize(global::System.Text.Json.JsonSerializer.Deserialize(ref reader, (global::System.Text.Json.Serialization.Metadata.JsonTypeInfo)options.GetTypeInfo(typeof(global::System.Int32))));
+#else
+ return ReferenceVo.__Deserialize(reader.GetInt32());
+#endif
+ }
+
+ public override void Write(System.Text.Json.Utf8JsonWriter writer, ReferenceVo value, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ #if NET5_0_OR_GREATER
+ global::System.Text.Json.JsonSerializer.Serialize(writer, value.Value, options);
+ #else
+ writer.WriteNumberValue(value.Value);
+ #endif
+ }
+
+#if NET6_0_OR_GREATER
+ public override ReferenceVo ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ return ReferenceVo.__Deserialize(global::System.Int32.Parse(reader.GetString(), global::System.Globalization.NumberStyles.Any, global::System.Globalization.CultureInfo.InvariantCulture));
+ }
+
+ public override void WriteAsPropertyName(System.Text.Json.Utf8JsonWriter writer, ReferenceVo value, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture));
+ }
+#endif
+ }
+
+
+ class ReferenceVoTypeConverter : global::System.ComponentModel.TypeConverter
+ {
+ public override global::System.Boolean CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType)
+ {
+ return sourceType == typeof(global::System.Int32) || sourceType == typeof(global::System.String) || base.CanConvertFrom(context, sourceType);
+ }
+
+ public override global::System.Object ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, global::System.Object value)
+ {
+ return value switch
+ {
+ global::System.Int32 intValue => ReferenceVo.__Deserialize(intValue),
+ global::System.String stringValue when !global::System.String.IsNullOrEmpty(stringValue) && global::System.Int32.TryParse(stringValue, out var result) => ReferenceVo.__Deserialize(result),
+ _ => base.ConvertFrom(context, culture, value),
+ };
+ }
+
+ public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType)
+ {
+ return sourceType == typeof(global::System.Int32) || sourceType == typeof(global::System.String) || base.CanConvertTo(context, sourceType);
+ }
+
+ public override object ConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, global::System.Object value, global::System.Type destinationType)
+ {
+ if (value is ReferenceVo idValue)
+ {
+ if (destinationType == typeof(global::System.Int32))
+ {
+ return idValue.Value;
+ }
+
+ if (destinationType == typeof(global::System.String))
+ {
+ return idValue.Value.ToString();
+ }
+ }
+
+ return base.ConvertTo(context, culture, value, destinationType);
+ }
+ }
+
+
+
+
+
+ internal sealed class ReferenceVoDebugView
+ {
+ private readonly ReferenceVo _t;
+
+ ReferenceVoDebugView(ReferenceVo t)
+ {
+ _t = t;
+ }
+
+ public global::System.String UnderlyingType => "System.Int32";
+ public System.Int32 Value => _t.Value ;
+
+ public global::System.String Conversions => @"[global::System.Text.Json.Serialization.JsonConverter(typeof(ReferenceVoSystemTextJsonConverter))]
+[global::System.ComponentModel.TypeConverter(typeof(ReferenceVoTypeConverter))]
+";
+ }
+ }
+
+}
+]
\ No newline at end of file
diff --git a/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v5.0/DeserializationStrictnessTests.Can_disallow_nulls_for_reference_value_objects.verified.txt b/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v5.0/DeserializationStrictnessTests.Can_disallow_nulls_for_reference_value_objects.verified.txt
new file mode 100644
index 0000000000..54a4599ab7
--- /dev/null
+++ b/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v5.0/DeserializationStrictnessTests.Can_disallow_nulls_for_reference_value_objects.verified.txt
@@ -0,0 +1,535 @@
+[
+// ------------------------------------------------------------------------------
+//
+// This code was generated by a source generator named Vogen (https://github.com/SteveDunn/Vogen)
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// ------------------------------------------------------------------------------
+
+// Suppress warnings about [Obsolete] member usage in generated code.
+#pragma warning disable CS0618
+
+// Suppress warnings for 'Override methods on comparable types'.
+#pragma warning disable CA1036
+
+// Suppress Error MA0097 : A class that implements IComparable or IComparable should override comparison operators
+#pragma warning disable MA0097
+
+// Suppress warning for 'The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source.'
+// The generator copies signatures from the BCL, e.g. for `TryParse`, and some of those have nullable annotations.
+#pragma warning disable CS8669
+
+// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
+#pragma warning disable CS1591
+
+namespace generator;
+
+public class VogenTypesFactory : global::System.Text.Json.Serialization.JsonConverterFactory
+{
+ public VogenTypesFactory() { }
+ private static readonly global::System.Collections.Generic.Dictionary> _lookup =
+ new global::System.Collections.Generic.Dictionary> {
+ { typeof(Whatever.ReferenceVo), new global::System.Lazy(() => new Whatever.ReferenceVo.ReferenceVoSystemTextJsonConverter()) }
+ };
+
+ public override bool CanConvert(global::System.Type typeToConvert) => _lookup.ContainsKey(typeToConvert);
+
+ public override global::System.Text.Json.Serialization.JsonConverter CreateConverter(global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) =>
+ _lookup[typeToConvert].Value;
+}
+
+// ------------------------------------------------------------------------------
+//
+// This code was generated by a source generator named Vogen (https://github.com/SteveDunn/Vogen)
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// ------------------------------------------------------------------------------
+
+// Suppress warnings about [Obsolete] member usage in generated code.
+#pragma warning disable CS0618
+
+// Suppress warnings for 'Override methods on comparable types'.
+#pragma warning disable CA1036
+
+// Suppress Error MA0097 : A class that implements IComparable or IComparable should override comparison operators
+#pragma warning disable MA0097
+
+// Suppress warning for 'The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source.'
+// The generator copies signatures from the BCL, e.g. for `TryParse`, and some of those have nullable annotations.
+#pragma warning disable CS8669
+
+// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
+#pragma warning disable CS1591
+
+using Vogen;
+
+namespace Whatever
+{
+
+ [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Vogen", "1.0.0.0")]
+ [global::System.Text.Json.Serialization.JsonConverter(typeof(ReferenceVoSystemTextJsonConverter))]
+[global::System.ComponentModel.TypeConverter(typeof(ReferenceVoTypeConverter))]
+
+ [global::System.Diagnostics.DebuggerTypeProxyAttribute(typeof(ReferenceVoDebugView))]
+ [global::System.Diagnostics.DebuggerDisplayAttribute("Underlying type: System.Int32, Value = { _value }")]
+ public partial class ReferenceVo : global::System.IEquatable, global::System.IEquatable , global::System.IComparable, global::System.IComparable
+ {
+#if DEBUG
+ private readonly global::System.Diagnostics.StackTrace _stackTrace = null;
+#endif
+ private readonly global::System.Boolean _isInitialized;
+ private readonly System.Int32 _value;
+
+///
+/// Gets the underlying value if set, otherwise a is thrown.
+///
+public System.Int32 Value
+ {
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ get
+ {
+ EnsureInitialized();
+ return _value;
+ }
+ }
+
+
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
+ public ReferenceVo()
+ {
+#if DEBUG
+ _stackTrace = new global::System.Diagnostics.StackTrace();
+#endif
+ _isInitialized = false;
+ _value = default;
+ }
+
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ private ReferenceVo(System.Int32 value)
+ {
+ _value = value;
+ _isInitialized = true;
+ }
+
+ ///
+ /// Builds an instance from the provided underlying type.
+ ///
+ /// The underlying type.
+ /// An instance of this type.
+ public static ReferenceVo From(System.Int32 value)
+ {
+
+
+
+
+
+
+ ReferenceVo instance = new ReferenceVo(value);
+
+ return instance;
+ }
+
+ ///
+/// Tries to build an instance from the provided underlying type.
+/// If a normalization method is provided, it will be called.
+/// If validation is provided, and it fails, false will be returned.
+///
+/// The underlying type.
+/// An instance of the value object.
+/// True if the value object can be built, otherwise false.
+public static bool TryFrom(System.Int32 value,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo vo)
+{
+
+
+
+
+
+ vo = new ReferenceVo(value);
+
+ return true;
+}///
+/// Tries to build an instance from the provided underlying value.
+/// If a normalization method is provided, it will be called.
+/// If validation is provided, and it fails, an error will be returned.
+///
+/// The primitive value.
+/// A containing either the value object, or an error.
+public static ValueObjectOrError TryFrom(System.Int32 value)
+{
+
+
+
+
+
+
+ return new ValueObjectOrError(new ReferenceVo(value));
+}
+
+ public bool IsInitialized() => _isInitialized;
+
+
+
+ // only called internally when something has been deserialized into
+ // its primitive type.
+ private static ReferenceVo __Deserialize(System.Int32 value)
+ {
+
+
+
+
+
+
+ return new ReferenceVo(value);
+ }
+
+ public global::System.Boolean Equals(ReferenceVo other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ // It's possible to create uninitialized instances via converters such as EfCore (HasDefaultValue), which call Equals.
+ // We treat anything uninitialized as not equal to anything, even other uninitialized instances of this type.
+ if(!_isInitialized || !other._isInitialized) return false;
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ return GetType() == other.GetType() && global::System.Collections.Generic.EqualityComparer.Default.Equals(Value, other.Value);
+ }
+ public global::System.Boolean Equals(ReferenceVo other, global::System.Collections.Generic.IEqualityComparer comparer)
+ {
+ return comparer.Equals(this, other);
+ }
+
+
+ public global::System.Boolean Equals(System.Int32 primitive)
+ {
+ return Value.Equals(primitive);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object obj)
+ {
+ return Equals(obj as ReferenceVo);
+ }
+
+ public static global::System.Boolean operator ==(ReferenceVo left, ReferenceVo right) => Equals(left, right);
+ public static global::System.Boolean operator !=(ReferenceVo left, ReferenceVo right) => !Equals(left, right);
+
+ public static global::System.Boolean operator ==(ReferenceVo left, System.Int32 right) => Equals(left.Value, right);
+ public static global::System.Boolean operator !=(ReferenceVo left, System.Int32 right) => !Equals(left.Value, right);
+
+ public static global::System.Boolean operator ==(System.Int32 left, ReferenceVo right) => Equals(left, right.Value);
+ public static global::System.Boolean operator !=(System.Int32 left, ReferenceVo right) => !Equals(left, right.Value);
+
+ public static explicit operator ReferenceVo(System.Int32 value) => From(value);
+ public static explicit operator System.Int32(ReferenceVo value) => value.Value;
+
+ public int CompareTo(ReferenceVo other) => Value.CompareTo(other.Value);
+ public int CompareTo(object other) {
+ if(other is null) return 1;
+ if(other is ReferenceVo x) return CompareTo(x);
+ throw new global::System.ArgumentException("Cannot compare to object as it is not of type ReferenceVo", nameof(other));
+ }
+
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(global::System.ReadOnlySpan s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, style, provider, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(global::System.ReadOnlySpan s,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(string s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, style, provider, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(string s,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(global::System.ReadOnlySpan s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, style, provider);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s) {
+ var r = System.Int32.Parse(s);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.Globalization.NumberStyles style) {
+ var r = System.Int32.Parse(s, style);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, style, provider);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, provider);
+ return From(r);
+ }
+
+
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked // Overflow is fine, just wrap
+ {
+ global::System.Int32 hash = (global::System.Int32) 2166136261;
+ hash = (hash * 16777619) ^ GetType().GetHashCode();
+ hash = (hash * 16777619) ^ global::System.Collections.Generic.EqualityComparer.Default.GetHashCode(Value);
+ return hash;
+ }
+ }
+
+ private void EnsureInitialized()
+ {
+ if (!_isInitialized)
+ {
+#if DEBUG
+ global::System.String message = "Use of uninitialized Value Object at: " + _stackTrace ?? "";
+#else
+ global::System.String message = "Use of uninitialized Value Object.";
+#endif
+
+ throw new global::Vogen.ValueObjectValidationException(message);
+ }
+ }
+
+
+
+
+ /// Returns the string representation of the underlying .
+ public override global::System.String ToString() =>_isInitialized ? Value.ToString() : "[UNINITIALIZED]";
+
+
+ ///
+ /// Converts a ReferenceVo to or from JSON.
+ ///
+ public class ReferenceVoSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter
+ {
+ #if NET5_0_OR_GREATER
+ public override bool HandleNull => true;
+ #endif
+ public override ReferenceVo Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options)
+ {
+#if NET5_0_OR_GREATER
+ return ReferenceVo.__Deserialize(global::System.Text.Json.JsonSerializer.Deserialize(ref reader, (global::System.Text.Json.Serialization.Metadata.JsonTypeInfo)options.GetTypeInfo(typeof(global::System.Int32))));
+#else
+ return ReferenceVo.__Deserialize(reader.GetInt32());
+#endif
+ }
+
+ public override void Write(System.Text.Json.Utf8JsonWriter writer, ReferenceVo value, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ #if NET5_0_OR_GREATER
+ global::System.Text.Json.JsonSerializer.Serialize(writer, value.Value, options);
+ #else
+ writer.WriteNumberValue(value.Value);
+ #endif
+ }
+
+#if NET6_0_OR_GREATER
+ public override ReferenceVo ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ return ReferenceVo.__Deserialize(global::System.Int32.Parse(reader.GetString(), global::System.Globalization.NumberStyles.Any, global::System.Globalization.CultureInfo.InvariantCulture));
+ }
+
+ public override void WriteAsPropertyName(System.Text.Json.Utf8JsonWriter writer, ReferenceVo value, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture));
+ }
+#endif
+ }
+
+
+ class ReferenceVoTypeConverter : global::System.ComponentModel.TypeConverter
+ {
+ public override global::System.Boolean CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType)
+ {
+ return sourceType == typeof(global::System.Int32) || sourceType == typeof(global::System.String) || base.CanConvertFrom(context, sourceType);
+ }
+
+ public override global::System.Object ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, global::System.Object value)
+ {
+ return value switch
+ {
+ global::System.Int32 intValue => ReferenceVo.__Deserialize(intValue),
+ global::System.String stringValue when !global::System.String.IsNullOrEmpty(stringValue) && global::System.Int32.TryParse(stringValue, out var result) => ReferenceVo.__Deserialize(result),
+ _ => base.ConvertFrom(context, culture, value),
+ };
+ }
+
+ public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType)
+ {
+ return sourceType == typeof(global::System.Int32) || sourceType == typeof(global::System.String) || base.CanConvertTo(context, sourceType);
+ }
+
+ public override object ConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, global::System.Object value, global::System.Type destinationType)
+ {
+ if (value is ReferenceVo idValue)
+ {
+ if (destinationType == typeof(global::System.Int32))
+ {
+ return idValue.Value;
+ }
+
+ if (destinationType == typeof(global::System.String))
+ {
+ return idValue.Value.ToString();
+ }
+ }
+
+ return base.ConvertTo(context, culture, value, destinationType);
+ }
+ }
+
+
+
+
+
+ internal sealed class ReferenceVoDebugView
+ {
+ private readonly ReferenceVo _t;
+
+ ReferenceVoDebugView(ReferenceVo t)
+ {
+ _t = t;
+ }
+
+ public global::System.String UnderlyingType => "System.Int32";
+ public System.Int32 Value => _t.Value ;
+
+ public global::System.String Conversions => @"[global::System.Text.Json.Serialization.JsonConverter(typeof(ReferenceVoSystemTextJsonConverter))]
+[global::System.ComponentModel.TypeConverter(typeof(ReferenceVoTypeConverter))]
+";
+ }
+ }
+
+}
+]
\ No newline at end of file
diff --git a/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v5.0/DeserializationStrictnessTests.Reference_value_objects_allow_nulls_by_default.verified.txt b/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v5.0/DeserializationStrictnessTests.Reference_value_objects_allow_nulls_by_default.verified.txt
new file mode 100644
index 0000000000..0fb35503af
--- /dev/null
+++ b/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v5.0/DeserializationStrictnessTests.Reference_value_objects_allow_nulls_by_default.verified.txt
@@ -0,0 +1,532 @@
+[
+// ------------------------------------------------------------------------------
+//
+// This code was generated by a source generator named Vogen (https://github.com/SteveDunn/Vogen)
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// ------------------------------------------------------------------------------
+
+// Suppress warnings about [Obsolete] member usage in generated code.
+#pragma warning disable CS0618
+
+// Suppress warnings for 'Override methods on comparable types'.
+#pragma warning disable CA1036
+
+// Suppress Error MA0097 : A class that implements IComparable or IComparable should override comparison operators
+#pragma warning disable MA0097
+
+// Suppress warning for 'The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source.'
+// The generator copies signatures from the BCL, e.g. for `TryParse`, and some of those have nullable annotations.
+#pragma warning disable CS8669
+
+// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
+#pragma warning disable CS1591
+
+namespace generator;
+
+public class VogenTypesFactory : global::System.Text.Json.Serialization.JsonConverterFactory
+{
+ public VogenTypesFactory() { }
+ private static readonly global::System.Collections.Generic.Dictionary> _lookup =
+ new global::System.Collections.Generic.Dictionary> {
+ { typeof(Whatever.ReferenceVo), new global::System.Lazy(() => new Whatever.ReferenceVo.ReferenceVoSystemTextJsonConverter()) }
+ };
+
+ public override bool CanConvert(global::System.Type typeToConvert) => _lookup.ContainsKey(typeToConvert);
+
+ public override global::System.Text.Json.Serialization.JsonConverter CreateConverter(global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) =>
+ _lookup[typeToConvert].Value;
+}
+
+// ------------------------------------------------------------------------------
+//
+// This code was generated by a source generator named Vogen (https://github.com/SteveDunn/Vogen)
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// ------------------------------------------------------------------------------
+
+// Suppress warnings about [Obsolete] member usage in generated code.
+#pragma warning disable CS0618
+
+// Suppress warnings for 'Override methods on comparable types'.
+#pragma warning disable CA1036
+
+// Suppress Error MA0097 : A class that implements IComparable or IComparable should override comparison operators
+#pragma warning disable MA0097
+
+// Suppress warning for 'The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source.'
+// The generator copies signatures from the BCL, e.g. for `TryParse`, and some of those have nullable annotations.
+#pragma warning disable CS8669
+
+// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
+#pragma warning disable CS1591
+
+using Vogen;
+
+namespace Whatever
+{
+
+ [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Vogen", "1.0.0.0")]
+ [global::System.Text.Json.Serialization.JsonConverter(typeof(ReferenceVoSystemTextJsonConverter))]
+[global::System.ComponentModel.TypeConverter(typeof(ReferenceVoTypeConverter))]
+
+ [global::System.Diagnostics.DebuggerTypeProxyAttribute(typeof(ReferenceVoDebugView))]
+ [global::System.Diagnostics.DebuggerDisplayAttribute("Underlying type: System.Int32, Value = { _value }")]
+ public partial class ReferenceVo : global::System.IEquatable, global::System.IEquatable , global::System.IComparable, global::System.IComparable
+ {
+#if DEBUG
+ private readonly global::System.Diagnostics.StackTrace _stackTrace = null;
+#endif
+ private readonly global::System.Boolean _isInitialized;
+ private readonly System.Int32 _value;
+
+///
+/// Gets the underlying value if set, otherwise a is thrown.
+///
+public System.Int32 Value
+ {
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ get
+ {
+ EnsureInitialized();
+ return _value;
+ }
+ }
+
+
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
+ public ReferenceVo()
+ {
+#if DEBUG
+ _stackTrace = new global::System.Diagnostics.StackTrace();
+#endif
+ _isInitialized = false;
+ _value = default;
+ }
+
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ private ReferenceVo(System.Int32 value)
+ {
+ _value = value;
+ _isInitialized = true;
+ }
+
+ ///
+ /// Builds an instance from the provided underlying type.
+ ///
+ /// The underlying type.
+ /// An instance of this type.
+ public static ReferenceVo From(System.Int32 value)
+ {
+
+
+
+
+
+
+ ReferenceVo instance = new ReferenceVo(value);
+
+ return instance;
+ }
+
+ ///
+/// Tries to build an instance from the provided underlying type.
+/// If a normalization method is provided, it will be called.
+/// If validation is provided, and it fails, false will be returned.
+///
+/// The underlying type.
+/// An instance of the value object.
+/// True if the value object can be built, otherwise false.
+public static bool TryFrom(System.Int32 value,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo vo)
+{
+
+
+
+
+
+ vo = new ReferenceVo(value);
+
+ return true;
+}///
+/// Tries to build an instance from the provided underlying value.
+/// If a normalization method is provided, it will be called.
+/// If validation is provided, and it fails, an error will be returned.
+///
+/// The primitive value.
+/// A containing either the value object, or an error.
+public static ValueObjectOrError TryFrom(System.Int32 value)
+{
+
+
+
+
+
+
+ return new ValueObjectOrError(new ReferenceVo(value));
+}
+
+ public bool IsInitialized() => _isInitialized;
+
+
+
+ // only called internally when something has been deserialized into
+ // its primitive type.
+ private static ReferenceVo __Deserialize(System.Int32 value)
+ {
+
+
+
+
+
+
+ return new ReferenceVo(value);
+ }
+
+ public global::System.Boolean Equals(ReferenceVo other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ // It's possible to create uninitialized instances via converters such as EfCore (HasDefaultValue), which call Equals.
+ // We treat anything uninitialized as not equal to anything, even other uninitialized instances of this type.
+ if(!_isInitialized || !other._isInitialized) return false;
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ return GetType() == other.GetType() && global::System.Collections.Generic.EqualityComparer.Default.Equals(Value, other.Value);
+ }
+ public global::System.Boolean Equals(ReferenceVo other, global::System.Collections.Generic.IEqualityComparer comparer)
+ {
+ return comparer.Equals(this, other);
+ }
+
+
+ public global::System.Boolean Equals(System.Int32 primitive)
+ {
+ return Value.Equals(primitive);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object obj)
+ {
+ return Equals(obj as ReferenceVo);
+ }
+
+ public static global::System.Boolean operator ==(ReferenceVo left, ReferenceVo right) => Equals(left, right);
+ public static global::System.Boolean operator !=(ReferenceVo left, ReferenceVo right) => !Equals(left, right);
+
+ public static global::System.Boolean operator ==(ReferenceVo left, System.Int32 right) => Equals(left.Value, right);
+ public static global::System.Boolean operator !=(ReferenceVo left, System.Int32 right) => !Equals(left.Value, right);
+
+ public static global::System.Boolean operator ==(System.Int32 left, ReferenceVo right) => Equals(left, right.Value);
+ public static global::System.Boolean operator !=(System.Int32 left, ReferenceVo right) => !Equals(left, right.Value);
+
+ public static explicit operator ReferenceVo(System.Int32 value) => From(value);
+ public static explicit operator System.Int32(ReferenceVo value) => value.Value;
+
+ public int CompareTo(ReferenceVo other) => Value.CompareTo(other.Value);
+ public int CompareTo(object other) {
+ if(other is null) return 1;
+ if(other is ReferenceVo x) return CompareTo(x);
+ throw new global::System.ArgumentException("Cannot compare to object as it is not of type ReferenceVo", nameof(other));
+ }
+
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(global::System.ReadOnlySpan s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, style, provider, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(global::System.ReadOnlySpan s,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(string s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, style, provider, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(string s,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(global::System.ReadOnlySpan s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, style, provider);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s) {
+ var r = System.Int32.Parse(s);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.Globalization.NumberStyles style) {
+ var r = System.Int32.Parse(s, style);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, style, provider);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, provider);
+ return From(r);
+ }
+
+
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked // Overflow is fine, just wrap
+ {
+ global::System.Int32 hash = (global::System.Int32) 2166136261;
+ hash = (hash * 16777619) ^ GetType().GetHashCode();
+ hash = (hash * 16777619) ^ global::System.Collections.Generic.EqualityComparer.Default.GetHashCode(Value);
+ return hash;
+ }
+ }
+
+ private void EnsureInitialized()
+ {
+ if (!_isInitialized)
+ {
+#if DEBUG
+ global::System.String message = "Use of uninitialized Value Object at: " + _stackTrace ?? "";
+#else
+ global::System.String message = "Use of uninitialized Value Object.";
+#endif
+
+ throw new global::Vogen.ValueObjectValidationException(message);
+ }
+ }
+
+
+
+
+ /// Returns the string representation of the underlying .
+ public override global::System.String ToString() =>_isInitialized ? Value.ToString() : "[UNINITIALIZED]";
+
+
+ ///
+ /// Converts a ReferenceVo to or from JSON.
+ ///
+ public class ReferenceVoSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter
+ {
+ public override ReferenceVo Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options)
+ {
+#if NET5_0_OR_GREATER
+ return ReferenceVo.__Deserialize(global::System.Text.Json.JsonSerializer.Deserialize(ref reader, (global::System.Text.Json.Serialization.Metadata.JsonTypeInfo)options.GetTypeInfo(typeof(global::System.Int32))));
+#else
+ return ReferenceVo.__Deserialize(reader.GetInt32());
+#endif
+ }
+
+ public override void Write(System.Text.Json.Utf8JsonWriter writer, ReferenceVo value, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ #if NET5_0_OR_GREATER
+ global::System.Text.Json.JsonSerializer.Serialize(writer, value.Value, options);
+ #else
+ writer.WriteNumberValue(value.Value);
+ #endif
+ }
+
+#if NET6_0_OR_GREATER
+ public override ReferenceVo ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ return ReferenceVo.__Deserialize(global::System.Int32.Parse(reader.GetString(), global::System.Globalization.NumberStyles.Any, global::System.Globalization.CultureInfo.InvariantCulture));
+ }
+
+ public override void WriteAsPropertyName(System.Text.Json.Utf8JsonWriter writer, ReferenceVo value, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture));
+ }
+#endif
+ }
+
+
+ class ReferenceVoTypeConverter : global::System.ComponentModel.TypeConverter
+ {
+ public override global::System.Boolean CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType)
+ {
+ return sourceType == typeof(global::System.Int32) || sourceType == typeof(global::System.String) || base.CanConvertFrom(context, sourceType);
+ }
+
+ public override global::System.Object ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, global::System.Object value)
+ {
+ return value switch
+ {
+ global::System.Int32 intValue => ReferenceVo.__Deserialize(intValue),
+ global::System.String stringValue when !global::System.String.IsNullOrEmpty(stringValue) && global::System.Int32.TryParse(stringValue, out var result) => ReferenceVo.__Deserialize(result),
+ _ => base.ConvertFrom(context, culture, value),
+ };
+ }
+
+ public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType)
+ {
+ return sourceType == typeof(global::System.Int32) || sourceType == typeof(global::System.String) || base.CanConvertTo(context, sourceType);
+ }
+
+ public override object ConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, global::System.Object value, global::System.Type destinationType)
+ {
+ if (value is ReferenceVo idValue)
+ {
+ if (destinationType == typeof(global::System.Int32))
+ {
+ return idValue.Value;
+ }
+
+ if (destinationType == typeof(global::System.String))
+ {
+ return idValue.Value.ToString();
+ }
+ }
+
+ return base.ConvertTo(context, culture, value, destinationType);
+ }
+ }
+
+
+
+
+
+ internal sealed class ReferenceVoDebugView
+ {
+ private readonly ReferenceVo _t;
+
+ ReferenceVoDebugView(ReferenceVo t)
+ {
+ _t = t;
+ }
+
+ public global::System.String UnderlyingType => "System.Int32";
+ public System.Int32 Value => _t.Value ;
+
+ public global::System.String Conversions => @"[global::System.Text.Json.Serialization.JsonConverter(typeof(ReferenceVoSystemTextJsonConverter))]
+[global::System.ComponentModel.TypeConverter(typeof(ReferenceVoTypeConverter))]
+";
+ }
+ }
+
+}
+]
\ No newline at end of file
diff --git a/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v6.0/DeserializationStrictnessTests.Can_disallow_nulls_for_reference_value_objects.verified.txt b/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v6.0/DeserializationStrictnessTests.Can_disallow_nulls_for_reference_value_objects.verified.txt
new file mode 100644
index 0000000000..54a4599ab7
--- /dev/null
+++ b/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v6.0/DeserializationStrictnessTests.Can_disallow_nulls_for_reference_value_objects.verified.txt
@@ -0,0 +1,535 @@
+[
+// ------------------------------------------------------------------------------
+//
+// This code was generated by a source generator named Vogen (https://github.com/SteveDunn/Vogen)
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// ------------------------------------------------------------------------------
+
+// Suppress warnings about [Obsolete] member usage in generated code.
+#pragma warning disable CS0618
+
+// Suppress warnings for 'Override methods on comparable types'.
+#pragma warning disable CA1036
+
+// Suppress Error MA0097 : A class that implements IComparable or IComparable should override comparison operators
+#pragma warning disable MA0097
+
+// Suppress warning for 'The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source.'
+// The generator copies signatures from the BCL, e.g. for `TryParse`, and some of those have nullable annotations.
+#pragma warning disable CS8669
+
+// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
+#pragma warning disable CS1591
+
+namespace generator;
+
+public class VogenTypesFactory : global::System.Text.Json.Serialization.JsonConverterFactory
+{
+ public VogenTypesFactory() { }
+ private static readonly global::System.Collections.Generic.Dictionary> _lookup =
+ new global::System.Collections.Generic.Dictionary> {
+ { typeof(Whatever.ReferenceVo), new global::System.Lazy(() => new Whatever.ReferenceVo.ReferenceVoSystemTextJsonConverter()) }
+ };
+
+ public override bool CanConvert(global::System.Type typeToConvert) => _lookup.ContainsKey(typeToConvert);
+
+ public override global::System.Text.Json.Serialization.JsonConverter CreateConverter(global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) =>
+ _lookup[typeToConvert].Value;
+}
+
+// ------------------------------------------------------------------------------
+//
+// This code was generated by a source generator named Vogen (https://github.com/SteveDunn/Vogen)
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// ------------------------------------------------------------------------------
+
+// Suppress warnings about [Obsolete] member usage in generated code.
+#pragma warning disable CS0618
+
+// Suppress warnings for 'Override methods on comparable types'.
+#pragma warning disable CA1036
+
+// Suppress Error MA0097 : A class that implements IComparable or IComparable should override comparison operators
+#pragma warning disable MA0097
+
+// Suppress warning for 'The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source.'
+// The generator copies signatures from the BCL, e.g. for `TryParse`, and some of those have nullable annotations.
+#pragma warning disable CS8669
+
+// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
+#pragma warning disable CS1591
+
+using Vogen;
+
+namespace Whatever
+{
+
+ [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Vogen", "1.0.0.0")]
+ [global::System.Text.Json.Serialization.JsonConverter(typeof(ReferenceVoSystemTextJsonConverter))]
+[global::System.ComponentModel.TypeConverter(typeof(ReferenceVoTypeConverter))]
+
+ [global::System.Diagnostics.DebuggerTypeProxyAttribute(typeof(ReferenceVoDebugView))]
+ [global::System.Diagnostics.DebuggerDisplayAttribute("Underlying type: System.Int32, Value = { _value }")]
+ public partial class ReferenceVo : global::System.IEquatable, global::System.IEquatable , global::System.IComparable, global::System.IComparable
+ {
+#if DEBUG
+ private readonly global::System.Diagnostics.StackTrace _stackTrace = null;
+#endif
+ private readonly global::System.Boolean _isInitialized;
+ private readonly System.Int32 _value;
+
+///
+/// Gets the underlying value if set, otherwise a is thrown.
+///
+public System.Int32 Value
+ {
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ get
+ {
+ EnsureInitialized();
+ return _value;
+ }
+ }
+
+
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
+ public ReferenceVo()
+ {
+#if DEBUG
+ _stackTrace = new global::System.Diagnostics.StackTrace();
+#endif
+ _isInitialized = false;
+ _value = default;
+ }
+
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ private ReferenceVo(System.Int32 value)
+ {
+ _value = value;
+ _isInitialized = true;
+ }
+
+ ///
+ /// Builds an instance from the provided underlying type.
+ ///
+ /// The underlying type.
+ /// An instance of this type.
+ public static ReferenceVo From(System.Int32 value)
+ {
+
+
+
+
+
+
+ ReferenceVo instance = new ReferenceVo(value);
+
+ return instance;
+ }
+
+ ///
+/// Tries to build an instance from the provided underlying type.
+/// If a normalization method is provided, it will be called.
+/// If validation is provided, and it fails, false will be returned.
+///
+/// The underlying type.
+/// An instance of the value object.
+/// True if the value object can be built, otherwise false.
+public static bool TryFrom(System.Int32 value,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo vo)
+{
+
+
+
+
+
+ vo = new ReferenceVo(value);
+
+ return true;
+}///
+/// Tries to build an instance from the provided underlying value.
+/// If a normalization method is provided, it will be called.
+/// If validation is provided, and it fails, an error will be returned.
+///
+/// The primitive value.
+/// A containing either the value object, or an error.
+public static ValueObjectOrError TryFrom(System.Int32 value)
+{
+
+
+
+
+
+
+ return new ValueObjectOrError(new ReferenceVo(value));
+}
+
+ public bool IsInitialized() => _isInitialized;
+
+
+
+ // only called internally when something has been deserialized into
+ // its primitive type.
+ private static ReferenceVo __Deserialize(System.Int32 value)
+ {
+
+
+
+
+
+
+ return new ReferenceVo(value);
+ }
+
+ public global::System.Boolean Equals(ReferenceVo other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ // It's possible to create uninitialized instances via converters such as EfCore (HasDefaultValue), which call Equals.
+ // We treat anything uninitialized as not equal to anything, even other uninitialized instances of this type.
+ if(!_isInitialized || !other._isInitialized) return false;
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ return GetType() == other.GetType() && global::System.Collections.Generic.EqualityComparer.Default.Equals(Value, other.Value);
+ }
+ public global::System.Boolean Equals(ReferenceVo other, global::System.Collections.Generic.IEqualityComparer comparer)
+ {
+ return comparer.Equals(this, other);
+ }
+
+
+ public global::System.Boolean Equals(System.Int32 primitive)
+ {
+ return Value.Equals(primitive);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object obj)
+ {
+ return Equals(obj as ReferenceVo);
+ }
+
+ public static global::System.Boolean operator ==(ReferenceVo left, ReferenceVo right) => Equals(left, right);
+ public static global::System.Boolean operator !=(ReferenceVo left, ReferenceVo right) => !Equals(left, right);
+
+ public static global::System.Boolean operator ==(ReferenceVo left, System.Int32 right) => Equals(left.Value, right);
+ public static global::System.Boolean operator !=(ReferenceVo left, System.Int32 right) => !Equals(left.Value, right);
+
+ public static global::System.Boolean operator ==(System.Int32 left, ReferenceVo right) => Equals(left, right.Value);
+ public static global::System.Boolean operator !=(System.Int32 left, ReferenceVo right) => !Equals(left, right.Value);
+
+ public static explicit operator ReferenceVo(System.Int32 value) => From(value);
+ public static explicit operator System.Int32(ReferenceVo value) => value.Value;
+
+ public int CompareTo(ReferenceVo other) => Value.CompareTo(other.Value);
+ public int CompareTo(object other) {
+ if(other is null) return 1;
+ if(other is ReferenceVo x) return CompareTo(x);
+ throw new global::System.ArgumentException("Cannot compare to object as it is not of type ReferenceVo", nameof(other));
+ }
+
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(global::System.ReadOnlySpan s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, style, provider, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(global::System.ReadOnlySpan s,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(string s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, style, provider, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(string s,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(global::System.ReadOnlySpan s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, style, provider);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s) {
+ var r = System.Int32.Parse(s);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.Globalization.NumberStyles style) {
+ var r = System.Int32.Parse(s, style);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, style, provider);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, provider);
+ return From(r);
+ }
+
+
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked // Overflow is fine, just wrap
+ {
+ global::System.Int32 hash = (global::System.Int32) 2166136261;
+ hash = (hash * 16777619) ^ GetType().GetHashCode();
+ hash = (hash * 16777619) ^ global::System.Collections.Generic.EqualityComparer.Default.GetHashCode(Value);
+ return hash;
+ }
+ }
+
+ private void EnsureInitialized()
+ {
+ if (!_isInitialized)
+ {
+#if DEBUG
+ global::System.String message = "Use of uninitialized Value Object at: " + _stackTrace ?? "";
+#else
+ global::System.String message = "Use of uninitialized Value Object.";
+#endif
+
+ throw new global::Vogen.ValueObjectValidationException(message);
+ }
+ }
+
+
+
+
+ /// Returns the string representation of the underlying .
+ public override global::System.String ToString() =>_isInitialized ? Value.ToString() : "[UNINITIALIZED]";
+
+
+ ///
+ /// Converts a ReferenceVo to or from JSON.
+ ///
+ public class ReferenceVoSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter
+ {
+ #if NET5_0_OR_GREATER
+ public override bool HandleNull => true;
+ #endif
+ public override ReferenceVo Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options)
+ {
+#if NET5_0_OR_GREATER
+ return ReferenceVo.__Deserialize(global::System.Text.Json.JsonSerializer.Deserialize(ref reader, (global::System.Text.Json.Serialization.Metadata.JsonTypeInfo)options.GetTypeInfo(typeof(global::System.Int32))));
+#else
+ return ReferenceVo.__Deserialize(reader.GetInt32());
+#endif
+ }
+
+ public override void Write(System.Text.Json.Utf8JsonWriter writer, ReferenceVo value, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ #if NET5_0_OR_GREATER
+ global::System.Text.Json.JsonSerializer.Serialize(writer, value.Value, options);
+ #else
+ writer.WriteNumberValue(value.Value);
+ #endif
+ }
+
+#if NET6_0_OR_GREATER
+ public override ReferenceVo ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ return ReferenceVo.__Deserialize(global::System.Int32.Parse(reader.GetString(), global::System.Globalization.NumberStyles.Any, global::System.Globalization.CultureInfo.InvariantCulture));
+ }
+
+ public override void WriteAsPropertyName(System.Text.Json.Utf8JsonWriter writer, ReferenceVo value, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture));
+ }
+#endif
+ }
+
+
+ class ReferenceVoTypeConverter : global::System.ComponentModel.TypeConverter
+ {
+ public override global::System.Boolean CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType)
+ {
+ return sourceType == typeof(global::System.Int32) || sourceType == typeof(global::System.String) || base.CanConvertFrom(context, sourceType);
+ }
+
+ public override global::System.Object ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, global::System.Object value)
+ {
+ return value switch
+ {
+ global::System.Int32 intValue => ReferenceVo.__Deserialize(intValue),
+ global::System.String stringValue when !global::System.String.IsNullOrEmpty(stringValue) && global::System.Int32.TryParse(stringValue, out var result) => ReferenceVo.__Deserialize(result),
+ _ => base.ConvertFrom(context, culture, value),
+ };
+ }
+
+ public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType)
+ {
+ return sourceType == typeof(global::System.Int32) || sourceType == typeof(global::System.String) || base.CanConvertTo(context, sourceType);
+ }
+
+ public override object ConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, global::System.Object value, global::System.Type destinationType)
+ {
+ if (value is ReferenceVo idValue)
+ {
+ if (destinationType == typeof(global::System.Int32))
+ {
+ return idValue.Value;
+ }
+
+ if (destinationType == typeof(global::System.String))
+ {
+ return idValue.Value.ToString();
+ }
+ }
+
+ return base.ConvertTo(context, culture, value, destinationType);
+ }
+ }
+
+
+
+
+
+ internal sealed class ReferenceVoDebugView
+ {
+ private readonly ReferenceVo _t;
+
+ ReferenceVoDebugView(ReferenceVo t)
+ {
+ _t = t;
+ }
+
+ public global::System.String UnderlyingType => "System.Int32";
+ public System.Int32 Value => _t.Value ;
+
+ public global::System.String Conversions => @"[global::System.Text.Json.Serialization.JsonConverter(typeof(ReferenceVoSystemTextJsonConverter))]
+[global::System.ComponentModel.TypeConverter(typeof(ReferenceVoTypeConverter))]
+";
+ }
+ }
+
+}
+]
\ No newline at end of file
diff --git a/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v6.0/DeserializationStrictnessTests.Reference_value_objects_allow_nulls_by_default.verified.txt b/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v6.0/DeserializationStrictnessTests.Reference_value_objects_allow_nulls_by_default.verified.txt
new file mode 100644
index 0000000000..0fb35503af
--- /dev/null
+++ b/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v6.0/DeserializationStrictnessTests.Reference_value_objects_allow_nulls_by_default.verified.txt
@@ -0,0 +1,532 @@
+[
+// ------------------------------------------------------------------------------
+//
+// This code was generated by a source generator named Vogen (https://github.com/SteveDunn/Vogen)
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// ------------------------------------------------------------------------------
+
+// Suppress warnings about [Obsolete] member usage in generated code.
+#pragma warning disable CS0618
+
+// Suppress warnings for 'Override methods on comparable types'.
+#pragma warning disable CA1036
+
+// Suppress Error MA0097 : A class that implements IComparable or IComparable should override comparison operators
+#pragma warning disable MA0097
+
+// Suppress warning for 'The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source.'
+// The generator copies signatures from the BCL, e.g. for `TryParse`, and some of those have nullable annotations.
+#pragma warning disable CS8669
+
+// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
+#pragma warning disable CS1591
+
+namespace generator;
+
+public class VogenTypesFactory : global::System.Text.Json.Serialization.JsonConverterFactory
+{
+ public VogenTypesFactory() { }
+ private static readonly global::System.Collections.Generic.Dictionary> _lookup =
+ new global::System.Collections.Generic.Dictionary> {
+ { typeof(Whatever.ReferenceVo), new global::System.Lazy(() => new Whatever.ReferenceVo.ReferenceVoSystemTextJsonConverter()) }
+ };
+
+ public override bool CanConvert(global::System.Type typeToConvert) => _lookup.ContainsKey(typeToConvert);
+
+ public override global::System.Text.Json.Serialization.JsonConverter CreateConverter(global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) =>
+ _lookup[typeToConvert].Value;
+}
+
+// ------------------------------------------------------------------------------
+//
+// This code was generated by a source generator named Vogen (https://github.com/SteveDunn/Vogen)
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// ------------------------------------------------------------------------------
+
+// Suppress warnings about [Obsolete] member usage in generated code.
+#pragma warning disable CS0618
+
+// Suppress warnings for 'Override methods on comparable types'.
+#pragma warning disable CA1036
+
+// Suppress Error MA0097 : A class that implements IComparable or IComparable should override comparison operators
+#pragma warning disable MA0097
+
+// Suppress warning for 'The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source.'
+// The generator copies signatures from the BCL, e.g. for `TryParse`, and some of those have nullable annotations.
+#pragma warning disable CS8669
+
+// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
+#pragma warning disable CS1591
+
+using Vogen;
+
+namespace Whatever
+{
+
+ [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Vogen", "1.0.0.0")]
+ [global::System.Text.Json.Serialization.JsonConverter(typeof(ReferenceVoSystemTextJsonConverter))]
+[global::System.ComponentModel.TypeConverter(typeof(ReferenceVoTypeConverter))]
+
+ [global::System.Diagnostics.DebuggerTypeProxyAttribute(typeof(ReferenceVoDebugView))]
+ [global::System.Diagnostics.DebuggerDisplayAttribute("Underlying type: System.Int32, Value = { _value }")]
+ public partial class ReferenceVo : global::System.IEquatable, global::System.IEquatable , global::System.IComparable, global::System.IComparable
+ {
+#if DEBUG
+ private readonly global::System.Diagnostics.StackTrace _stackTrace = null;
+#endif
+ private readonly global::System.Boolean _isInitialized;
+ private readonly System.Int32 _value;
+
+///
+/// Gets the underlying value if set, otherwise a is thrown.
+///
+public System.Int32 Value
+ {
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ get
+ {
+ EnsureInitialized();
+ return _value;
+ }
+ }
+
+
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
+ public ReferenceVo()
+ {
+#if DEBUG
+ _stackTrace = new global::System.Diagnostics.StackTrace();
+#endif
+ _isInitialized = false;
+ _value = default;
+ }
+
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ private ReferenceVo(System.Int32 value)
+ {
+ _value = value;
+ _isInitialized = true;
+ }
+
+ ///
+ /// Builds an instance from the provided underlying type.
+ ///
+ /// The underlying type.
+ /// An instance of this type.
+ public static ReferenceVo From(System.Int32 value)
+ {
+
+
+
+
+
+
+ ReferenceVo instance = new ReferenceVo(value);
+
+ return instance;
+ }
+
+ ///
+/// Tries to build an instance from the provided underlying type.
+/// If a normalization method is provided, it will be called.
+/// If validation is provided, and it fails, false will be returned.
+///
+/// The underlying type.
+/// An instance of the value object.
+/// True if the value object can be built, otherwise false.
+public static bool TryFrom(System.Int32 value,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo vo)
+{
+
+
+
+
+
+ vo = new ReferenceVo(value);
+
+ return true;
+}///
+/// Tries to build an instance from the provided underlying value.
+/// If a normalization method is provided, it will be called.
+/// If validation is provided, and it fails, an error will be returned.
+///
+/// The primitive value.
+/// A containing either the value object, or an error.
+public static ValueObjectOrError TryFrom(System.Int32 value)
+{
+
+
+
+
+
+
+ return new ValueObjectOrError(new ReferenceVo(value));
+}
+
+ public bool IsInitialized() => _isInitialized;
+
+
+
+ // only called internally when something has been deserialized into
+ // its primitive type.
+ private static ReferenceVo __Deserialize(System.Int32 value)
+ {
+
+
+
+
+
+
+ return new ReferenceVo(value);
+ }
+
+ public global::System.Boolean Equals(ReferenceVo other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ // It's possible to create uninitialized instances via converters such as EfCore (HasDefaultValue), which call Equals.
+ // We treat anything uninitialized as not equal to anything, even other uninitialized instances of this type.
+ if(!_isInitialized || !other._isInitialized) return false;
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ return GetType() == other.GetType() && global::System.Collections.Generic.EqualityComparer.Default.Equals(Value, other.Value);
+ }
+ public global::System.Boolean Equals(ReferenceVo other, global::System.Collections.Generic.IEqualityComparer comparer)
+ {
+ return comparer.Equals(this, other);
+ }
+
+
+ public global::System.Boolean Equals(System.Int32 primitive)
+ {
+ return Value.Equals(primitive);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object obj)
+ {
+ return Equals(obj as ReferenceVo);
+ }
+
+ public static global::System.Boolean operator ==(ReferenceVo left, ReferenceVo right) => Equals(left, right);
+ public static global::System.Boolean operator !=(ReferenceVo left, ReferenceVo right) => !Equals(left, right);
+
+ public static global::System.Boolean operator ==(ReferenceVo left, System.Int32 right) => Equals(left.Value, right);
+ public static global::System.Boolean operator !=(ReferenceVo left, System.Int32 right) => !Equals(left.Value, right);
+
+ public static global::System.Boolean operator ==(System.Int32 left, ReferenceVo right) => Equals(left, right.Value);
+ public static global::System.Boolean operator !=(System.Int32 left, ReferenceVo right) => !Equals(left, right.Value);
+
+ public static explicit operator ReferenceVo(System.Int32 value) => From(value);
+ public static explicit operator System.Int32(ReferenceVo value) => value.Value;
+
+ public int CompareTo(ReferenceVo other) => Value.CompareTo(other.Value);
+ public int CompareTo(object other) {
+ if(other is null) return 1;
+ if(other is ReferenceVo x) return CompareTo(x);
+ throw new global::System.ArgumentException("Cannot compare to object as it is not of type ReferenceVo", nameof(other));
+ }
+
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(global::System.ReadOnlySpan s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, style, provider, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(global::System.ReadOnlySpan s,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(string s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, style, provider, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(string s,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(global::System.ReadOnlySpan s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, style, provider);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s) {
+ var r = System.Int32.Parse(s);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.Globalization.NumberStyles style) {
+ var r = System.Int32.Parse(s, style);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, style, provider);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, provider);
+ return From(r);
+ }
+
+
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked // Overflow is fine, just wrap
+ {
+ global::System.Int32 hash = (global::System.Int32) 2166136261;
+ hash = (hash * 16777619) ^ GetType().GetHashCode();
+ hash = (hash * 16777619) ^ global::System.Collections.Generic.EqualityComparer.Default.GetHashCode(Value);
+ return hash;
+ }
+ }
+
+ private void EnsureInitialized()
+ {
+ if (!_isInitialized)
+ {
+#if DEBUG
+ global::System.String message = "Use of uninitialized Value Object at: " + _stackTrace ?? "";
+#else
+ global::System.String message = "Use of uninitialized Value Object.";
+#endif
+
+ throw new global::Vogen.ValueObjectValidationException(message);
+ }
+ }
+
+
+
+
+ /// Returns the string representation of the underlying .
+ public override global::System.String ToString() =>_isInitialized ? Value.ToString() : "[UNINITIALIZED]";
+
+
+ ///
+ /// Converts a ReferenceVo to or from JSON.
+ ///
+ public class ReferenceVoSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter
+ {
+ public override ReferenceVo Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options)
+ {
+#if NET5_0_OR_GREATER
+ return ReferenceVo.__Deserialize(global::System.Text.Json.JsonSerializer.Deserialize(ref reader, (global::System.Text.Json.Serialization.Metadata.JsonTypeInfo)options.GetTypeInfo(typeof(global::System.Int32))));
+#else
+ return ReferenceVo.__Deserialize(reader.GetInt32());
+#endif
+ }
+
+ public override void Write(System.Text.Json.Utf8JsonWriter writer, ReferenceVo value, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ #if NET5_0_OR_GREATER
+ global::System.Text.Json.JsonSerializer.Serialize(writer, value.Value, options);
+ #else
+ writer.WriteNumberValue(value.Value);
+ #endif
+ }
+
+#if NET6_0_OR_GREATER
+ public override ReferenceVo ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ return ReferenceVo.__Deserialize(global::System.Int32.Parse(reader.GetString(), global::System.Globalization.NumberStyles.Any, global::System.Globalization.CultureInfo.InvariantCulture));
+ }
+
+ public override void WriteAsPropertyName(System.Text.Json.Utf8JsonWriter writer, ReferenceVo value, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture));
+ }
+#endif
+ }
+
+
+ class ReferenceVoTypeConverter : global::System.ComponentModel.TypeConverter
+ {
+ public override global::System.Boolean CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType)
+ {
+ return sourceType == typeof(global::System.Int32) || sourceType == typeof(global::System.String) || base.CanConvertFrom(context, sourceType);
+ }
+
+ public override global::System.Object ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, global::System.Object value)
+ {
+ return value switch
+ {
+ global::System.Int32 intValue => ReferenceVo.__Deserialize(intValue),
+ global::System.String stringValue when !global::System.String.IsNullOrEmpty(stringValue) && global::System.Int32.TryParse(stringValue, out var result) => ReferenceVo.__Deserialize(result),
+ _ => base.ConvertFrom(context, culture, value),
+ };
+ }
+
+ public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType)
+ {
+ return sourceType == typeof(global::System.Int32) || sourceType == typeof(global::System.String) || base.CanConvertTo(context, sourceType);
+ }
+
+ public override object ConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, global::System.Object value, global::System.Type destinationType)
+ {
+ if (value is ReferenceVo idValue)
+ {
+ if (destinationType == typeof(global::System.Int32))
+ {
+ return idValue.Value;
+ }
+
+ if (destinationType == typeof(global::System.String))
+ {
+ return idValue.Value.ToString();
+ }
+ }
+
+ return base.ConvertTo(context, culture, value, destinationType);
+ }
+ }
+
+
+
+
+
+ internal sealed class ReferenceVoDebugView
+ {
+ private readonly ReferenceVo _t;
+
+ ReferenceVoDebugView(ReferenceVo t)
+ {
+ _t = t;
+ }
+
+ public global::System.String UnderlyingType => "System.Int32";
+ public System.Int32 Value => _t.Value ;
+
+ public global::System.String Conversions => @"[global::System.Text.Json.Serialization.JsonConverter(typeof(ReferenceVoSystemTextJsonConverter))]
+[global::System.ComponentModel.TypeConverter(typeof(ReferenceVoTypeConverter))]
+";
+ }
+ }
+
+}
+]
\ No newline at end of file
diff --git a/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v7.0/DeserializationStrictnessTests.Can_disallow_nulls_for_reference_value_objects.verified.txt b/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v7.0/DeserializationStrictnessTests.Can_disallow_nulls_for_reference_value_objects.verified.txt
new file mode 100644
index 0000000000..4a4e863165
--- /dev/null
+++ b/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v7.0/DeserializationStrictnessTests.Can_disallow_nulls_for_reference_value_objects.verified.txt
@@ -0,0 +1,591 @@
+[
+// ------------------------------------------------------------------------------
+//
+// This code was generated by a source generator named Vogen (https://github.com/SteveDunn/Vogen)
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// ------------------------------------------------------------------------------
+
+// Suppress warnings about [Obsolete] member usage in generated code.
+#pragma warning disable CS0618
+
+// Suppress warnings for 'Override methods on comparable types'.
+#pragma warning disable CA1036
+
+// Suppress Error MA0097 : A class that implements IComparable or IComparable should override comparison operators
+#pragma warning disable MA0097
+
+// Suppress warning for 'The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source.'
+// The generator copies signatures from the BCL, e.g. for `TryParse`, and some of those have nullable annotations.
+#pragma warning disable CS8669
+
+// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
+#pragma warning disable CS1591
+
+namespace generator;
+
+public class VogenTypesFactory : global::System.Text.Json.Serialization.JsonConverterFactory
+{
+ public VogenTypesFactory() { }
+ private static readonly global::System.Collections.Generic.Dictionary> _lookup =
+ new global::System.Collections.Generic.Dictionary> {
+ { typeof(Whatever.ReferenceVo), new global::System.Lazy(() => new Whatever.ReferenceVo.ReferenceVoSystemTextJsonConverter()) }
+ };
+
+ public override bool CanConvert(global::System.Type typeToConvert) => _lookup.ContainsKey(typeToConvert);
+
+ public override global::System.Text.Json.Serialization.JsonConverter CreateConverter(global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) =>
+ _lookup[typeToConvert].Value;
+}
+
+// ------------------------------------------------------------------------------
+//
+// This code was generated by a source generator named Vogen (https://github.com/SteveDunn/Vogen)
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// ------------------------------------------------------------------------------
+
+// Suppress warnings about [Obsolete] member usage in generated code.
+#pragma warning disable CS0618
+
+// Suppress warnings for 'Override methods on comparable types'.
+#pragma warning disable CA1036
+
+// Suppress Error MA0097 : A class that implements IComparable or IComparable should override comparison operators
+#pragma warning disable MA0097
+
+// Suppress warning for 'The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source.'
+// The generator copies signatures from the BCL, e.g. for `TryParse`, and some of those have nullable annotations.
+#pragma warning disable CS8669
+
+// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
+#pragma warning disable CS1591
+
+using Vogen;
+
+namespace Whatever
+{
+
+ [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Vogen", "1.0.0.0")]
+ [global::System.Text.Json.Serialization.JsonConverter(typeof(ReferenceVoSystemTextJsonConverter))]
+[global::System.ComponentModel.TypeConverter(typeof(ReferenceVoTypeConverter))]
+
+ [global::System.Diagnostics.DebuggerTypeProxyAttribute(typeof(ReferenceVoDebugView))]
+ [global::System.Diagnostics.DebuggerDisplayAttribute("Underlying type: System.Int32, Value = { _value }")]
+ public partial class ReferenceVo : global::System.IEquatable, global::System.IEquatable , global::System.IComparable, global::System.IComparable, global::System.IParsable, global::System.ISpanParsable
+ {
+#if DEBUG
+ private readonly global::System.Diagnostics.StackTrace _stackTrace = null;
+#endif
+ private readonly global::System.Boolean _isInitialized;
+ private readonly System.Int32 _value;
+
+///
+/// Gets the underlying value if set, otherwise a is thrown.
+///
+public System.Int32 Value
+ {
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ get
+ {
+ EnsureInitialized();
+ return _value;
+ }
+ }
+
+
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
+ public ReferenceVo()
+ {
+#if DEBUG
+ _stackTrace = new global::System.Diagnostics.StackTrace();
+#endif
+ _isInitialized = false;
+ _value = default;
+ }
+
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ private ReferenceVo(System.Int32 value)
+ {
+ _value = value;
+ _isInitialized = true;
+ }
+
+ ///
+ /// Builds an instance from the provided underlying type.
+ ///
+ /// The underlying type.
+ /// An instance of this type.
+ public static ReferenceVo From(System.Int32 value)
+ {
+
+
+
+
+
+
+ ReferenceVo instance = new ReferenceVo(value);
+
+ return instance;
+ }
+
+ ///
+/// Tries to build an instance from the provided underlying type.
+/// If a normalization method is provided, it will be called.
+/// If validation is provided, and it fails, false will be returned.
+///
+/// The underlying type.
+/// An instance of the value object.
+/// True if the value object can be built, otherwise false.
+public static bool TryFrom(System.Int32 value,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo vo)
+{
+
+
+
+
+
+ vo = new ReferenceVo(value);
+
+ return true;
+}///
+/// Tries to build an instance from the provided underlying value.
+/// If a normalization method is provided, it will be called.
+/// If validation is provided, and it fails, an error will be returned.
+///
+/// The primitive value.
+/// A containing either the value object, or an error.
+public static ValueObjectOrError TryFrom(System.Int32 value)
+{
+
+
+
+
+
+
+ return new ValueObjectOrError(new ReferenceVo(value));
+}
+
+ public bool IsInitialized() => _isInitialized;
+
+
+
+ // only called internally when something has been deserialized into
+ // its primitive type.
+ private static ReferenceVo __Deserialize(System.Int32 value)
+ {
+
+
+
+
+
+
+ return new ReferenceVo(value);
+ }
+
+ public global::System.Boolean Equals(ReferenceVo other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ // It's possible to create uninitialized instances via converters such as EfCore (HasDefaultValue), which call Equals.
+ // We treat anything uninitialized as not equal to anything, even other uninitialized instances of this type.
+ if(!_isInitialized || !other._isInitialized) return false;
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ return GetType() == other.GetType() && global::System.Collections.Generic.EqualityComparer.Default.Equals(Value, other.Value);
+ }
+ public global::System.Boolean Equals(ReferenceVo other, global::System.Collections.Generic.IEqualityComparer comparer)
+ {
+ return comparer.Equals(this, other);
+ }
+
+
+ public global::System.Boolean Equals(System.Int32 primitive)
+ {
+ return Value.Equals(primitive);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object obj)
+ {
+ return Equals(obj as ReferenceVo);
+ }
+
+ public static global::System.Boolean operator ==(ReferenceVo left, ReferenceVo right) => Equals(left, right);
+ public static global::System.Boolean operator !=(ReferenceVo left, ReferenceVo right) => !Equals(left, right);
+
+ public static global::System.Boolean operator ==(ReferenceVo left, System.Int32 right) => Equals(left.Value, right);
+ public static global::System.Boolean operator !=(ReferenceVo left, System.Int32 right) => !Equals(left.Value, right);
+
+ public static global::System.Boolean operator ==(System.Int32 left, ReferenceVo right) => Equals(left, right.Value);
+ public static global::System.Boolean operator !=(System.Int32 left, ReferenceVo right) => !Equals(left, right.Value);
+
+ public static explicit operator ReferenceVo(System.Int32 value) => From(value);
+ public static explicit operator System.Int32(ReferenceVo value) => value.Value;
+
+ public int CompareTo(ReferenceVo other) => Value.CompareTo(other.Value);
+ public int CompareTo(object other) {
+ if(other is null) return 1;
+ if(other is ReferenceVo x) return CompareTo(x);
+ throw new global::System.ArgumentException("Cannot compare to object as it is not of type ReferenceVo", nameof(other));
+ }
+
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(global::System.ReadOnlySpan s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, style, provider, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(global::System.ReadOnlySpan s, global::System.IFormatProvider provider,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, provider, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(global::System.ReadOnlySpan s,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(string s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, style, provider, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(string s, global::System.IFormatProvider provider,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, provider, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(string s,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(global::System.ReadOnlySpan s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, style, provider);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(global::System.ReadOnlySpan s, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, provider);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s) {
+ var r = System.Int32.Parse(s);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.Globalization.NumberStyles style) {
+ var r = System.Int32.Parse(s, style);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, style, provider);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, provider);
+ return From(r);
+ }
+
+
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked // Overflow is fine, just wrap
+ {
+ global::System.Int32 hash = (global::System.Int32) 2166136261;
+ hash = (hash * 16777619) ^ GetType().GetHashCode();
+ hash = (hash * 16777619) ^ global::System.Collections.Generic.EqualityComparer.Default.GetHashCode(Value);
+ return hash;
+ }
+ }
+
+ private void EnsureInitialized()
+ {
+ if (!_isInitialized)
+ {
+#if DEBUG
+ global::System.String message = "Use of uninitialized Value Object at: " + _stackTrace ?? "";
+#else
+ global::System.String message = "Use of uninitialized Value Object.";
+#endif
+
+ throw new global::Vogen.ValueObjectValidationException(message);
+ }
+ }
+
+
+
+
+ /// Returns the string representation of the underlying .
+ public override global::System.String ToString() =>_isInitialized ? Value.ToString() : "[UNINITIALIZED]";
+
+
+ ///
+ /// Converts a ReferenceVo to or from JSON.
+ ///
+ public class ReferenceVoSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter
+ {
+ #if NET5_0_OR_GREATER
+ public override bool HandleNull => true;
+ #endif
+ public override ReferenceVo Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options)
+ {
+#if NET5_0_OR_GREATER
+ return ReferenceVo.__Deserialize(global::System.Text.Json.JsonSerializer.Deserialize(ref reader, (global::System.Text.Json.Serialization.Metadata.JsonTypeInfo)options.GetTypeInfo(typeof(global::System.Int32))));
+#else
+ return ReferenceVo.__Deserialize(reader.GetInt32());
+#endif
+ }
+
+ public override void Write(System.Text.Json.Utf8JsonWriter writer, ReferenceVo value, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ #if NET5_0_OR_GREATER
+ global::System.Text.Json.JsonSerializer.Serialize(writer, value.Value, options);
+ #else
+ writer.WriteNumberValue(value.Value);
+ #endif
+ }
+
+#if NET6_0_OR_GREATER
+ public override ReferenceVo ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ return ReferenceVo.__Deserialize(global::System.Int32.Parse(reader.GetString(), global::System.Globalization.NumberStyles.Any, global::System.Globalization.CultureInfo.InvariantCulture));
+ }
+
+ public override void WriteAsPropertyName(System.Text.Json.Utf8JsonWriter writer, ReferenceVo value, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture));
+ }
+#endif
+ }
+
+
+ class ReferenceVoTypeConverter : global::System.ComponentModel.TypeConverter
+ {
+ public override global::System.Boolean CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType)
+ {
+ return sourceType == typeof(global::System.Int32) || sourceType == typeof(global::System.String) || base.CanConvertFrom(context, sourceType);
+ }
+
+ public override global::System.Object ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, global::System.Object value)
+ {
+ return value switch
+ {
+ global::System.Int32 intValue => ReferenceVo.__Deserialize(intValue),
+ global::System.String stringValue when !global::System.String.IsNullOrEmpty(stringValue) && global::System.Int32.TryParse(stringValue, out var result) => ReferenceVo.__Deserialize(result),
+ _ => base.ConvertFrom(context, culture, value),
+ };
+ }
+
+ public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType)
+ {
+ return sourceType == typeof(global::System.Int32) || sourceType == typeof(global::System.String) || base.CanConvertTo(context, sourceType);
+ }
+
+ public override object ConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, global::System.Object value, global::System.Type destinationType)
+ {
+ if (value is ReferenceVo idValue)
+ {
+ if (destinationType == typeof(global::System.Int32))
+ {
+ return idValue.Value;
+ }
+
+ if (destinationType == typeof(global::System.String))
+ {
+ return idValue.Value.ToString();
+ }
+ }
+
+ return base.ConvertTo(context, culture, value, destinationType);
+ }
+ }
+
+
+
+
+
+ internal sealed class ReferenceVoDebugView
+ {
+ private readonly ReferenceVo _t;
+
+ ReferenceVoDebugView(ReferenceVo t)
+ {
+ _t = t;
+ }
+
+ public global::System.String UnderlyingType => "System.Int32";
+ public System.Int32 Value => _t.Value ;
+
+ public global::System.String Conversions => @"[global::System.Text.Json.Serialization.JsonConverter(typeof(ReferenceVoSystemTextJsonConverter))]
+[global::System.ComponentModel.TypeConverter(typeof(ReferenceVoTypeConverter))]
+";
+ }
+ }
+
+}
+]
\ No newline at end of file
diff --git a/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v7.0/DeserializationStrictnessTests.Reference_value_objects_allow_nulls_by_default.verified.txt b/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v7.0/DeserializationStrictnessTests.Reference_value_objects_allow_nulls_by_default.verified.txt
new file mode 100644
index 0000000000..d99fafc137
--- /dev/null
+++ b/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v7.0/DeserializationStrictnessTests.Reference_value_objects_allow_nulls_by_default.verified.txt
@@ -0,0 +1,588 @@
+[
+// ------------------------------------------------------------------------------
+//
+// This code was generated by a source generator named Vogen (https://github.com/SteveDunn/Vogen)
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// ------------------------------------------------------------------------------
+
+// Suppress warnings about [Obsolete] member usage in generated code.
+#pragma warning disable CS0618
+
+// Suppress warnings for 'Override methods on comparable types'.
+#pragma warning disable CA1036
+
+// Suppress Error MA0097 : A class that implements IComparable or IComparable should override comparison operators
+#pragma warning disable MA0097
+
+// Suppress warning for 'The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source.'
+// The generator copies signatures from the BCL, e.g. for `TryParse`, and some of those have nullable annotations.
+#pragma warning disable CS8669
+
+// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
+#pragma warning disable CS1591
+
+namespace generator;
+
+public class VogenTypesFactory : global::System.Text.Json.Serialization.JsonConverterFactory
+{
+ public VogenTypesFactory() { }
+ private static readonly global::System.Collections.Generic.Dictionary> _lookup =
+ new global::System.Collections.Generic.Dictionary> {
+ { typeof(Whatever.ReferenceVo), new global::System.Lazy(() => new Whatever.ReferenceVo.ReferenceVoSystemTextJsonConverter()) }
+ };
+
+ public override bool CanConvert(global::System.Type typeToConvert) => _lookup.ContainsKey(typeToConvert);
+
+ public override global::System.Text.Json.Serialization.JsonConverter CreateConverter(global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) =>
+ _lookup[typeToConvert].Value;
+}
+
+// ------------------------------------------------------------------------------
+//
+// This code was generated by a source generator named Vogen (https://github.com/SteveDunn/Vogen)
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// ------------------------------------------------------------------------------
+
+// Suppress warnings about [Obsolete] member usage in generated code.
+#pragma warning disable CS0618
+
+// Suppress warnings for 'Override methods on comparable types'.
+#pragma warning disable CA1036
+
+// Suppress Error MA0097 : A class that implements IComparable or IComparable should override comparison operators
+#pragma warning disable MA0097
+
+// Suppress warning for 'The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source.'
+// The generator copies signatures from the BCL, e.g. for `TryParse`, and some of those have nullable annotations.
+#pragma warning disable CS8669
+
+// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
+#pragma warning disable CS1591
+
+using Vogen;
+
+namespace Whatever
+{
+
+ [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Vogen", "1.0.0.0")]
+ [global::System.Text.Json.Serialization.JsonConverter(typeof(ReferenceVoSystemTextJsonConverter))]
+[global::System.ComponentModel.TypeConverter(typeof(ReferenceVoTypeConverter))]
+
+ [global::System.Diagnostics.DebuggerTypeProxyAttribute(typeof(ReferenceVoDebugView))]
+ [global::System.Diagnostics.DebuggerDisplayAttribute("Underlying type: System.Int32, Value = { _value }")]
+ public partial class ReferenceVo : global::System.IEquatable, global::System.IEquatable , global::System.IComparable, global::System.IComparable, global::System.IParsable, global::System.ISpanParsable
+ {
+#if DEBUG
+ private readonly global::System.Diagnostics.StackTrace _stackTrace = null;
+#endif
+ private readonly global::System.Boolean _isInitialized;
+ private readonly System.Int32 _value;
+
+///
+/// Gets the underlying value if set, otherwise a is thrown.
+///
+public System.Int32 Value
+ {
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ get
+ {
+ EnsureInitialized();
+ return _value;
+ }
+ }
+
+
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
+ public ReferenceVo()
+ {
+#if DEBUG
+ _stackTrace = new global::System.Diagnostics.StackTrace();
+#endif
+ _isInitialized = false;
+ _value = default;
+ }
+
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ private ReferenceVo(System.Int32 value)
+ {
+ _value = value;
+ _isInitialized = true;
+ }
+
+ ///
+ /// Builds an instance from the provided underlying type.
+ ///
+ /// The underlying type.
+ /// An instance of this type.
+ public static ReferenceVo From(System.Int32 value)
+ {
+
+
+
+
+
+
+ ReferenceVo instance = new ReferenceVo(value);
+
+ return instance;
+ }
+
+ ///
+/// Tries to build an instance from the provided underlying type.
+/// If a normalization method is provided, it will be called.
+/// If validation is provided, and it fails, false will be returned.
+///
+/// The underlying type.
+/// An instance of the value object.
+/// True if the value object can be built, otherwise false.
+public static bool TryFrom(System.Int32 value,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo vo)
+{
+
+
+
+
+
+ vo = new ReferenceVo(value);
+
+ return true;
+}///
+/// Tries to build an instance from the provided underlying value.
+/// If a normalization method is provided, it will be called.
+/// If validation is provided, and it fails, an error will be returned.
+///
+/// The primitive value.
+/// A containing either the value object, or an error.
+public static ValueObjectOrError TryFrom(System.Int32 value)
+{
+
+
+
+
+
+
+ return new ValueObjectOrError(new ReferenceVo(value));
+}
+
+ public bool IsInitialized() => _isInitialized;
+
+
+
+ // only called internally when something has been deserialized into
+ // its primitive type.
+ private static ReferenceVo __Deserialize(System.Int32 value)
+ {
+
+
+
+
+
+
+ return new ReferenceVo(value);
+ }
+
+ public global::System.Boolean Equals(ReferenceVo other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ // It's possible to create uninitialized instances via converters such as EfCore (HasDefaultValue), which call Equals.
+ // We treat anything uninitialized as not equal to anything, even other uninitialized instances of this type.
+ if(!_isInitialized || !other._isInitialized) return false;
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ return GetType() == other.GetType() && global::System.Collections.Generic.EqualityComparer.Default.Equals(Value, other.Value);
+ }
+ public global::System.Boolean Equals(ReferenceVo other, global::System.Collections.Generic.IEqualityComparer comparer)
+ {
+ return comparer.Equals(this, other);
+ }
+
+
+ public global::System.Boolean Equals(System.Int32 primitive)
+ {
+ return Value.Equals(primitive);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object obj)
+ {
+ return Equals(obj as ReferenceVo);
+ }
+
+ public static global::System.Boolean operator ==(ReferenceVo left, ReferenceVo right) => Equals(left, right);
+ public static global::System.Boolean operator !=(ReferenceVo left, ReferenceVo right) => !Equals(left, right);
+
+ public static global::System.Boolean operator ==(ReferenceVo left, System.Int32 right) => Equals(left.Value, right);
+ public static global::System.Boolean operator !=(ReferenceVo left, System.Int32 right) => !Equals(left.Value, right);
+
+ public static global::System.Boolean operator ==(System.Int32 left, ReferenceVo right) => Equals(left, right.Value);
+ public static global::System.Boolean operator !=(System.Int32 left, ReferenceVo right) => !Equals(left, right.Value);
+
+ public static explicit operator ReferenceVo(System.Int32 value) => From(value);
+ public static explicit operator System.Int32(ReferenceVo value) => value.Value;
+
+ public int CompareTo(ReferenceVo other) => Value.CompareTo(other.Value);
+ public int CompareTo(object other) {
+ if(other is null) return 1;
+ if(other is ReferenceVo x) return CompareTo(x);
+ throw new global::System.ArgumentException("Cannot compare to object as it is not of type ReferenceVo", nameof(other));
+ }
+
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(global::System.ReadOnlySpan s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, style, provider, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(global::System.ReadOnlySpan s, global::System.IFormatProvider provider,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, provider, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(global::System.ReadOnlySpan s,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(string s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, style, provider, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(string s, global::System.IFormatProvider provider,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, provider, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(string s,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(global::System.ReadOnlySpan s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, style, provider);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(global::System.ReadOnlySpan s, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, provider);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s) {
+ var r = System.Int32.Parse(s);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.Globalization.NumberStyles style) {
+ var r = System.Int32.Parse(s, style);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, style, provider);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, provider);
+ return From(r);
+ }
+
+
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked // Overflow is fine, just wrap
+ {
+ global::System.Int32 hash = (global::System.Int32) 2166136261;
+ hash = (hash * 16777619) ^ GetType().GetHashCode();
+ hash = (hash * 16777619) ^ global::System.Collections.Generic.EqualityComparer.Default.GetHashCode(Value);
+ return hash;
+ }
+ }
+
+ private void EnsureInitialized()
+ {
+ if (!_isInitialized)
+ {
+#if DEBUG
+ global::System.String message = "Use of uninitialized Value Object at: " + _stackTrace ?? "";
+#else
+ global::System.String message = "Use of uninitialized Value Object.";
+#endif
+
+ throw new global::Vogen.ValueObjectValidationException(message);
+ }
+ }
+
+
+
+
+ /// Returns the string representation of the underlying .
+ public override global::System.String ToString() =>_isInitialized ? Value.ToString() : "[UNINITIALIZED]";
+
+
+ ///
+ /// Converts a ReferenceVo to or from JSON.
+ ///
+ public class ReferenceVoSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter
+ {
+ public override ReferenceVo Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options)
+ {
+#if NET5_0_OR_GREATER
+ return ReferenceVo.__Deserialize(global::System.Text.Json.JsonSerializer.Deserialize(ref reader, (global::System.Text.Json.Serialization.Metadata.JsonTypeInfo)options.GetTypeInfo(typeof(global::System.Int32))));
+#else
+ return ReferenceVo.__Deserialize(reader.GetInt32());
+#endif
+ }
+
+ public override void Write(System.Text.Json.Utf8JsonWriter writer, ReferenceVo value, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ #if NET5_0_OR_GREATER
+ global::System.Text.Json.JsonSerializer.Serialize(writer, value.Value, options);
+ #else
+ writer.WriteNumberValue(value.Value);
+ #endif
+ }
+
+#if NET6_0_OR_GREATER
+ public override ReferenceVo ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ return ReferenceVo.__Deserialize(global::System.Int32.Parse(reader.GetString(), global::System.Globalization.NumberStyles.Any, global::System.Globalization.CultureInfo.InvariantCulture));
+ }
+
+ public override void WriteAsPropertyName(System.Text.Json.Utf8JsonWriter writer, ReferenceVo value, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture));
+ }
+#endif
+ }
+
+
+ class ReferenceVoTypeConverter : global::System.ComponentModel.TypeConverter
+ {
+ public override global::System.Boolean CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType)
+ {
+ return sourceType == typeof(global::System.Int32) || sourceType == typeof(global::System.String) || base.CanConvertFrom(context, sourceType);
+ }
+
+ public override global::System.Object ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, global::System.Object value)
+ {
+ return value switch
+ {
+ global::System.Int32 intValue => ReferenceVo.__Deserialize(intValue),
+ global::System.String stringValue when !global::System.String.IsNullOrEmpty(stringValue) && global::System.Int32.TryParse(stringValue, out var result) => ReferenceVo.__Deserialize(result),
+ _ => base.ConvertFrom(context, culture, value),
+ };
+ }
+
+ public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType)
+ {
+ return sourceType == typeof(global::System.Int32) || sourceType == typeof(global::System.String) || base.CanConvertTo(context, sourceType);
+ }
+
+ public override object ConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, global::System.Object value, global::System.Type destinationType)
+ {
+ if (value is ReferenceVo idValue)
+ {
+ if (destinationType == typeof(global::System.Int32))
+ {
+ return idValue.Value;
+ }
+
+ if (destinationType == typeof(global::System.String))
+ {
+ return idValue.Value.ToString();
+ }
+ }
+
+ return base.ConvertTo(context, culture, value, destinationType);
+ }
+ }
+
+
+
+
+
+ internal sealed class ReferenceVoDebugView
+ {
+ private readonly ReferenceVo _t;
+
+ ReferenceVoDebugView(ReferenceVo t)
+ {
+ _t = t;
+ }
+
+ public global::System.String UnderlyingType => "System.Int32";
+ public System.Int32 Value => _t.Value ;
+
+ public global::System.String Conversions => @"[global::System.Text.Json.Serialization.JsonConverter(typeof(ReferenceVoSystemTextJsonConverter))]
+[global::System.ComponentModel.TypeConverter(typeof(ReferenceVoTypeConverter))]
+";
+ }
+ }
+
+}
+]
\ No newline at end of file
diff --git a/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v8.0/DeserializationStrictnessTests.Can_disallow_nulls_for_reference_value_objects.verified.txt b/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v8.0/DeserializationStrictnessTests.Can_disallow_nulls_for_reference_value_objects.verified.txt
new file mode 100644
index 0000000000..36815e3bb9
--- /dev/null
+++ b/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v8.0/DeserializationStrictnessTests.Can_disallow_nulls_for_reference_value_objects.verified.txt
@@ -0,0 +1,681 @@
+[
+// ------------------------------------------------------------------------------
+//
+// This code was generated by a source generator named Vogen (https://github.com/SteveDunn/Vogen)
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// ------------------------------------------------------------------------------
+
+// Suppress warnings about [Obsolete] member usage in generated code.
+#pragma warning disable CS0618
+
+// Suppress warnings for 'Override methods on comparable types'.
+#pragma warning disable CA1036
+
+// Suppress Error MA0097 : A class that implements IComparable or IComparable should override comparison operators
+#pragma warning disable MA0097
+
+// Suppress warning for 'The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source.'
+// The generator copies signatures from the BCL, e.g. for `TryParse`, and some of those have nullable annotations.
+#pragma warning disable CS8669
+
+// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
+#pragma warning disable CS1591
+
+namespace generator;
+
+public class VogenTypesFactory : global::System.Text.Json.Serialization.JsonConverterFactory
+{
+ public VogenTypesFactory() { }
+ private static readonly global::System.Collections.Generic.Dictionary> _lookup =
+ new global::System.Collections.Generic.Dictionary> {
+ { typeof(Whatever.ReferenceVo), new global::System.Lazy(() => new Whatever.ReferenceVo.ReferenceVoSystemTextJsonConverter()) }
+ };
+
+ public override bool CanConvert(global::System.Type typeToConvert) => _lookup.ContainsKey(typeToConvert);
+
+ public override global::System.Text.Json.Serialization.JsonConverter CreateConverter(global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) =>
+ _lookup[typeToConvert].Value;
+}
+
+// ------------------------------------------------------------------------------
+//
+// This code was generated by a source generator named Vogen (https://github.com/SteveDunn/Vogen)
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// ------------------------------------------------------------------------------
+
+// Suppress warnings about [Obsolete] member usage in generated code.
+#pragma warning disable CS0618
+
+// Suppress warnings for 'Override methods on comparable types'.
+#pragma warning disable CA1036
+
+// Suppress Error MA0097 : A class that implements IComparable or IComparable should override comparison operators
+#pragma warning disable MA0097
+
+// Suppress warning for 'The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source.'
+// The generator copies signatures from the BCL, e.g. for `TryParse`, and some of those have nullable annotations.
+#pragma warning disable CS8669
+
+// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
+#pragma warning disable CS1591
+
+using Vogen;
+
+namespace Whatever
+{
+
+ [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Vogen", "1.0.0.0")]
+ [global::System.Text.Json.Serialization.JsonConverter(typeof(ReferenceVoSystemTextJsonConverter))]
+[global::System.ComponentModel.TypeConverter(typeof(ReferenceVoTypeConverter))]
+
+ [global::System.Diagnostics.DebuggerTypeProxyAttribute(typeof(ReferenceVoDebugView))]
+ [global::System.Diagnostics.DebuggerDisplayAttribute("Underlying type: System.Int32, Value = { _value }")]
+ public partial class ReferenceVo : global::System.IEquatable, global::System.IEquatable , global::System.IComparable, global::System.IComparable, global::System.IParsable, global::System.ISpanParsable, global::System.IUtf8SpanParsable
+ {
+#if DEBUG
+ private readonly global::System.Diagnostics.StackTrace _stackTrace = null;
+#endif
+ private readonly global::System.Boolean _isInitialized;
+ private readonly System.Int32 _value;
+
+///
+/// Gets the underlying value if set, otherwise a is thrown.
+///
+public System.Int32 Value
+ {
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ get
+ {
+ EnsureInitialized();
+ return _value;
+ }
+ }
+
+
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
+ public ReferenceVo()
+ {
+#if DEBUG
+ _stackTrace = new global::System.Diagnostics.StackTrace();
+#endif
+ _isInitialized = false;
+ _value = default;
+ }
+
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ private ReferenceVo(System.Int32 value)
+ {
+ _value = value;
+ _isInitialized = true;
+ }
+
+ ///
+ /// Builds an instance from the provided underlying type.
+ ///
+ /// The underlying type.
+ /// An instance of this type.
+ public static ReferenceVo From(System.Int32 value)
+ {
+
+
+
+
+
+
+ ReferenceVo instance = new ReferenceVo(value);
+
+ return instance;
+ }
+
+ ///
+/// Tries to build an instance from the provided underlying type.
+/// If a normalization method is provided, it will be called.
+/// If validation is provided, and it fails, false will be returned.
+///
+/// The underlying type.
+/// An instance of the value object.
+/// True if the value object can be built, otherwise false.
+public static bool TryFrom(System.Int32 value,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo vo)
+{
+
+
+
+
+
+ vo = new ReferenceVo(value);
+
+ return true;
+}///
+/// Tries to build an instance from the provided underlying value.
+/// If a normalization method is provided, it will be called.
+/// If validation is provided, and it fails, an error will be returned.
+///
+/// The primitive value.
+/// A containing either the value object, or an error.
+public static ValueObjectOrError TryFrom(System.Int32 value)
+{
+
+
+
+
+
+
+ return new ValueObjectOrError(new ReferenceVo(value));
+}
+
+ public bool IsInitialized() => _isInitialized;
+
+
+
+ // only called internally when something has been deserialized into
+ // its primitive type.
+ private static ReferenceVo __Deserialize(System.Int32 value)
+ {
+
+
+
+
+
+
+ return new ReferenceVo(value);
+ }
+
+ public global::System.Boolean Equals(ReferenceVo other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ // It's possible to create uninitialized instances via converters such as EfCore (HasDefaultValue), which call Equals.
+ // We treat anything uninitialized as not equal to anything, even other uninitialized instances of this type.
+ if(!_isInitialized || !other._isInitialized) return false;
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ return GetType() == other.GetType() && global::System.Collections.Generic.EqualityComparer.Default.Equals(Value, other.Value);
+ }
+ public global::System.Boolean Equals(ReferenceVo other, global::System.Collections.Generic.IEqualityComparer comparer)
+ {
+ return comparer.Equals(this, other);
+ }
+
+
+ public global::System.Boolean Equals(System.Int32 primitive)
+ {
+ return Value.Equals(primitive);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object obj)
+ {
+ return Equals(obj as ReferenceVo);
+ }
+
+ public static global::System.Boolean operator ==(ReferenceVo left, ReferenceVo right) => Equals(left, right);
+ public static global::System.Boolean operator !=(ReferenceVo left, ReferenceVo right) => !Equals(left, right);
+
+ public static global::System.Boolean operator ==(ReferenceVo left, System.Int32 right) => Equals(left.Value, right);
+ public static global::System.Boolean operator !=(ReferenceVo left, System.Int32 right) => !Equals(left.Value, right);
+
+ public static global::System.Boolean operator ==(System.Int32 left, ReferenceVo right) => Equals(left, right.Value);
+ public static global::System.Boolean operator !=(System.Int32 left, ReferenceVo right) => !Equals(left, right.Value);
+
+ public static explicit operator ReferenceVo(System.Int32 value) => From(value);
+ public static explicit operator System.Int32(ReferenceVo value) => value.Value;
+
+ public int CompareTo(ReferenceVo other) => Value.CompareTo(other.Value);
+ public int CompareTo(object other) {
+ if(other is null) return 1;
+ if(other is ReferenceVo x) return CompareTo(x);
+ throw new global::System.ArgumentException("Cannot compare to object as it is not of type ReferenceVo", nameof(other));
+ }
+
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(global::System.ReadOnlySpan utf8Text, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(utf8Text, style, provider, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(global::System.ReadOnlySpan utf8Text, global::System.IFormatProvider provider,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(utf8Text, provider, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(global::System.ReadOnlySpan utf8Text,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(utf8Text, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(global::System.ReadOnlySpan s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, style, provider, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(global::System.ReadOnlySpan s, global::System.IFormatProvider provider,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, provider, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(global::System.ReadOnlySpan s,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(string s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, style, provider, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(string s, global::System.IFormatProvider provider,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, provider, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// True if the value could a) be parsed by the underlying type, and b) passes any validation (after running any optional normalization).
+ ///
+ public static global::System.Boolean TryParse(string s,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo result) {
+ if(System.Int32.TryParse(s, out var __v)) {
+
+
+ result = new ReferenceVo(__v);
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(global::System.ReadOnlySpan utf8Text, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(utf8Text, style, provider);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(global::System.ReadOnlySpan utf8Text, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(utf8Text, provider);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(global::System.ReadOnlySpan s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, style, provider);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(global::System.ReadOnlySpan s, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, provider);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s) {
+ var r = System.Int32.Parse(s);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.Globalization.NumberStyles style) {
+ var r = System.Int32.Parse(s, style);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.Globalization.NumberStyles style, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, style, provider);
+ return From(r);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// The value created via the method.
+ ///
+ /// Thrown when the value can be parsed, but is not valid.
+ public static ReferenceVo Parse(string s, global::System.IFormatProvider provider) {
+ var r = System.Int32.Parse(s, provider);
+ return From(r);
+ }
+
+
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked // Overflow is fine, just wrap
+ {
+ global::System.Int32 hash = (global::System.Int32) 2166136261;
+ hash = (hash * 16777619) ^ GetType().GetHashCode();
+ hash = (hash * 16777619) ^ global::System.Collections.Generic.EqualityComparer.Default.GetHashCode(Value);
+ return hash;
+ }
+ }
+
+ private void EnsureInitialized()
+ {
+ if (!_isInitialized)
+ {
+#if DEBUG
+ global::System.String message = "Use of uninitialized Value Object at: " + _stackTrace ?? "";
+#else
+ global::System.String message = "Use of uninitialized Value Object.";
+#endif
+
+ throw new global::Vogen.ValueObjectValidationException(message);
+ }
+ }
+
+
+
+
+ /// Returns the string representation of the underlying .
+ public override global::System.String ToString() =>_isInitialized ? Value.ToString() : "[UNINITIALIZED]";
+
+
+ ///
+ /// Converts a ReferenceVo to or from JSON.
+ ///
+ public class ReferenceVoSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter
+ {
+ #if NET5_0_OR_GREATER
+ public override bool HandleNull => true;
+ #endif
+ public override ReferenceVo Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options)
+ {
+#if NET5_0_OR_GREATER
+ return ReferenceVo.__Deserialize(global::System.Text.Json.JsonSerializer.Deserialize(ref reader, (global::System.Text.Json.Serialization.Metadata.JsonTypeInfo)options.GetTypeInfo(typeof(global::System.Int32))));
+#else
+ return ReferenceVo.__Deserialize(reader.GetInt32());
+#endif
+ }
+
+ public override void Write(System.Text.Json.Utf8JsonWriter writer, ReferenceVo value, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ #if NET5_0_OR_GREATER
+ global::System.Text.Json.JsonSerializer.Serialize(writer, value.Value, options);
+ #else
+ writer.WriteNumberValue(value.Value);
+ #endif
+ }
+
+#if NET6_0_OR_GREATER
+ public override ReferenceVo ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ return ReferenceVo.__Deserialize(global::System.Int32.Parse(reader.GetString(), global::System.Globalization.NumberStyles.Any, global::System.Globalization.CultureInfo.InvariantCulture));
+ }
+
+ public override void WriteAsPropertyName(System.Text.Json.Utf8JsonWriter writer, ReferenceVo value, global::System.Text.Json.JsonSerializerOptions options)
+ {
+ writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture));
+ }
+#endif
+ }
+
+
+ class ReferenceVoTypeConverter : global::System.ComponentModel.TypeConverter
+ {
+ public override global::System.Boolean CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType)
+ {
+ return sourceType == typeof(global::System.Int32) || sourceType == typeof(global::System.String) || base.CanConvertFrom(context, sourceType);
+ }
+
+ public override global::System.Object ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, global::System.Object value)
+ {
+ return value switch
+ {
+ global::System.Int32 intValue => ReferenceVo.__Deserialize(intValue),
+ global::System.String stringValue when !global::System.String.IsNullOrEmpty(stringValue) && global::System.Int32.TryParse(stringValue, out var result) => ReferenceVo.__Deserialize(result),
+ _ => base.ConvertFrom(context, culture, value),
+ };
+ }
+
+ public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType)
+ {
+ return sourceType == typeof(global::System.Int32) || sourceType == typeof(global::System.String) || base.CanConvertTo(context, sourceType);
+ }
+
+ public override object ConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, global::System.Object value, global::System.Type destinationType)
+ {
+ if (value is ReferenceVo idValue)
+ {
+ if (destinationType == typeof(global::System.Int32))
+ {
+ return idValue.Value;
+ }
+
+ if (destinationType == typeof(global::System.String))
+ {
+ return idValue.Value.ToString();
+ }
+ }
+
+ return base.ConvertTo(context, culture, value, destinationType);
+ }
+ }
+
+
+
+
+
+ internal sealed class ReferenceVoDebugView
+ {
+ private readonly ReferenceVo _t;
+
+ ReferenceVoDebugView(ReferenceVo t)
+ {
+ _t = t;
+ }
+
+ public global::System.String UnderlyingType => "System.Int32";
+ public System.Int32 Value => _t.Value ;
+
+ public global::System.String Conversions => @"[global::System.Text.Json.Serialization.JsonConverter(typeof(ReferenceVoSystemTextJsonConverter))]
+[global::System.ComponentModel.TypeConverter(typeof(ReferenceVoTypeConverter))]
+";
+ }
+ }
+
+}
+]
\ No newline at end of file
diff --git a/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v8.0/DeserializationStrictnessTests.Reference_value_objects_allow_nulls_by_default.verified.txt b/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v8.0/DeserializationStrictnessTests.Reference_value_objects_allow_nulls_by_default.verified.txt
new file mode 100644
index 0000000000..dc1bc906e9
--- /dev/null
+++ b/tests/SnapshotTests/SystemTextJsonGeneration/snapshots/snap-v8.0/DeserializationStrictnessTests.Reference_value_objects_allow_nulls_by_default.verified.txt
@@ -0,0 +1,678 @@
+[
+// ------------------------------------------------------------------------------
+//
+// This code was generated by a source generator named Vogen (https://github.com/SteveDunn/Vogen)
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// ------------------------------------------------------------------------------
+
+// Suppress warnings about [Obsolete] member usage in generated code.
+#pragma warning disable CS0618
+
+// Suppress warnings for 'Override methods on comparable types'.
+#pragma warning disable CA1036
+
+// Suppress Error MA0097 : A class that implements IComparable or IComparable should override comparison operators
+#pragma warning disable MA0097
+
+// Suppress warning for 'The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source.'
+// The generator copies signatures from the BCL, e.g. for `TryParse`, and some of those have nullable annotations.
+#pragma warning disable CS8669
+
+// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
+#pragma warning disable CS1591
+
+namespace generator;
+
+public class VogenTypesFactory : global::System.Text.Json.Serialization.JsonConverterFactory
+{
+ public VogenTypesFactory() { }
+ private static readonly global::System.Collections.Generic.Dictionary> _lookup =
+ new global::System.Collections.Generic.Dictionary> {
+ { typeof(Whatever.ReferenceVo), new global::System.Lazy(() => new Whatever.ReferenceVo.ReferenceVoSystemTextJsonConverter()) }
+ };
+
+ public override bool CanConvert(global::System.Type typeToConvert) => _lookup.ContainsKey(typeToConvert);
+
+ public override global::System.Text.Json.Serialization.JsonConverter CreateConverter(global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) =>
+ _lookup[typeToConvert].Value;
+}
+
+// ------------------------------------------------------------------------------
+//
+// This code was generated by a source generator named Vogen (https://github.com/SteveDunn/Vogen)
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// ------------------------------------------------------------------------------
+
+// Suppress warnings about [Obsolete] member usage in generated code.
+#pragma warning disable CS0618
+
+// Suppress warnings for 'Override methods on comparable types'.
+#pragma warning disable CA1036
+
+// Suppress Error MA0097 : A class that implements IComparable or IComparable should override comparison operators
+#pragma warning disable MA0097
+
+// Suppress warning for 'The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source.'
+// The generator copies signatures from the BCL, e.g. for `TryParse`, and some of those have nullable annotations.
+#pragma warning disable CS8669
+
+// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
+#pragma warning disable CS1591
+
+using Vogen;
+
+namespace Whatever
+{
+
+ [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Vogen", "1.0.0.0")]
+ [global::System.Text.Json.Serialization.JsonConverter(typeof(ReferenceVoSystemTextJsonConverter))]
+[global::System.ComponentModel.TypeConverter(typeof(ReferenceVoTypeConverter))]
+
+ [global::System.Diagnostics.DebuggerTypeProxyAttribute(typeof(ReferenceVoDebugView))]
+ [global::System.Diagnostics.DebuggerDisplayAttribute("Underlying type: System.Int32, Value = { _value }")]
+ public partial class ReferenceVo : global::System.IEquatable, global::System.IEquatable , global::System.IComparable, global::System.IComparable, global::System.IParsable, global::System.ISpanParsable, global::System.IUtf8SpanParsable
+ {
+#if DEBUG
+ private readonly global::System.Diagnostics.StackTrace _stackTrace = null;
+#endif
+ private readonly global::System.Boolean _isInitialized;
+ private readonly System.Int32 _value;
+
+///
+/// Gets the underlying value if set, otherwise a is thrown.
+///
+public System.Int32 Value
+ {
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ get
+ {
+ EnsureInitialized();
+ return _value;
+ }
+ }
+
+
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
+ public ReferenceVo()
+ {
+#if DEBUG
+ _stackTrace = new global::System.Diagnostics.StackTrace();
+#endif
+ _isInitialized = false;
+ _value = default;
+ }
+
+ [global::System.Diagnostics.DebuggerStepThroughAttribute]
+ private ReferenceVo(System.Int32 value)
+ {
+ _value = value;
+ _isInitialized = true;
+ }
+
+ ///
+ /// Builds an instance from the provided underlying type.
+ ///
+ /// The underlying type.
+ /// An instance of this type.
+ public static ReferenceVo From(System.Int32 value)
+ {
+
+
+
+
+
+
+ ReferenceVo instance = new ReferenceVo(value);
+
+ return instance;
+ }
+
+ ///
+/// Tries to build an instance from the provided underlying type.
+/// If a normalization method is provided, it will be called.
+/// If validation is provided, and it fails, false will be returned.
+///
+/// The underlying type.
+/// An instance of the value object.
+/// True if the value object can be built, otherwise false.
+public static bool TryFrom(System.Int32 value,
+#if NETCOREAPP3_0_OR_GREATER
+[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ out ReferenceVo vo)
+{
+
+
+
+
+
+ vo = new ReferenceVo(value);
+
+ return true;
+}///
+/// Tries to build an instance from the provided underlying value.
+/// If a normalization method is provided, it will be called.
+/// If validation is provided, and it fails, an error will be returned.
+///
+/// The primitive value.
+/// A containing either the value object, or an error.
+public static ValueObjectOrError TryFrom(System.Int32 value)
+{
+
+
+
+
+
+
+ return new ValueObjectOrError(new ReferenceVo(value));
+}
+
+ public bool IsInitialized() => _isInitialized;
+
+
+
+ // only called internally when something has been deserialized into
+ // its primitive type.
+ private static ReferenceVo __Deserialize(System.Int32 value)
+ {
+
+
+
+
+
+
+ return new ReferenceVo(value);
+ }
+
+ public global::System.Boolean Equals(ReferenceVo other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ // It's possible to create uninitialized instances via converters such as EfCore (HasDefaultValue), which call Equals.
+ // We treat anything uninitialized as not equal to anything, even other uninitialized instances of this type.
+ if(!_isInitialized || !other._isInitialized) return false;
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ return GetType() == other.GetType() && global::System.Collections.Generic.EqualityComparer.Default.Equals(Value, other.Value);
+ }
+ public global::System.Boolean Equals(ReferenceVo other, global::System.Collections.Generic.IEqualityComparer