mapperly icon indicating copy to clipboard operation
mapperly copied to clipboard

Implement NullPropertyMappingStrategy to allow more flexibility when encountering null values

Open latonz opened this issue 3 years ago • 0 comments

Is 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; set; }

+    /// <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.

latonz avatar Jul 11 '22 09:07 latonz