Implement NullPropertyMappingStrategy to allow more flexibility when encountering null values
See original GitHub issueIs your feature request related to a problem? Please describe. See https://github.com/riok/mapperly/discussions/96. Main use case is to merge two instances while only setting values which are non-null.
Describe the solution you’d like Implement different strategies on how to handle null values when mapping property values.
API
public sealed class MapperAttribute : Attribute
{
+ [Obsolete($"Use {nameof(NullPropertyMappingStrategy)} instead")]
public bool ThrowOnPropertyMappingNullMismatch
{
get => NullPropertyMappingStrategy == NullPropertyMappingStrategy.SetOrThrowIfNull;
set => NullPropertyMappingStrategy = NullPropertyMappingStrategy.SetOrThrowIfNull;
}
+ /// <summary>
+ /// Specifies the behaviour how to handle property mappings when <c>null</c> values are involved.
+ /// </summary>
+ public NullPropertyMappingStrategy NullPropertyMappingStrategy { get; set; } = NullPropertyMappingStrategy.SetOrIgnoreIfNull;
}
+/// <summary>
+/// Strategies on how to handle <c>null</c> values when mapping property values.
+/// </summary>
+public enum NullPropertyMappingStrategy
+{
+ /// <summary>
+ /// Sets the value if the target is nullable or the source is not <c>null</c>.
+ /// Ignores the mapping if the source is <c>null</c> and the target is not nullable
+ /// </summary>
+ SetOrIgnoreIfNull,
+
+ /// <summary>
+ /// Sets the value if the target is nullable or the source is not <c>null</c>.
+ /// Throws if the source is <c>null</c> and the target is not nullable
+ /// </summary>
+ SetOrThrowIfNull,
+
+ /// <summary>
+ /// Sets the value if the target is nullable or the source is not <c>null</c>.
+ /// Sets a default value otherwise (<c>default</c> for value types, empty string for strings, <c>new()</c> for classes; throw if no parameterless ctor exists).
+ /// </summary>
+ SetOrDefaultIfNull,
+
+ /// <summary>
+ /// Ignores the property if the source is <c>null</c>.
+ /// </summary>
+ IgnoreIfNull,
+
+ /// <summary>
+ /// Sets the value if the source is not <c>null</c>.
+ /// Sets a default value otherwise.
+ /// Similar to <see cref="SetOrDefaultIfNull"/> but does never set <c>null</c> values.
+ /// </summary>
+ DefaultIfNull,
+}
Backward compatibility
SetOrIgnoreIfNull
is the same as ThrowOnPropertyMappingNullMismatch=false
, SetOrThrowIfNull
is the same as ThrowOnPropertyMappingNullMismatch=true
. The existing ThrowOnPropertyMappingNullMismatch
property is kept around but marked as obsolete. If ThrowOnPropertyMappingNullMismatch
is false
, the new NullPropertyMappingStrategy
should be used. If ThrowOnPropertyMappingNullMismatch
is true
, always SetOrThrowIfNull
should be used. The documentation should be updated accordingly.
Additional context See https://github.com/riok/mapperly/discussions/96 and https://github.com/riok/mapperly/discussions/452.
Issue Analytics
- State:
- Created a year ago
- Reactions:8
- Comments:16 (4 by maintainers)
Top GitHub Comments
Awesome, thanks for checking and the update! I tested with
2.8.0-next.1
and can confirm it seems to be working as expected 👍Ah got it, in the case you mentioned Mapperly is mapping to constructor parameters and not properties. The behaviour you expect should be the default behaviour, but there is a bug in
2.7.0
leading to the behaviour you observed. This bug should be resolved in2.8.0-next.1
.