Jacob Bundgaard
Jacob Bundgaard

Reputation: 1085

How to make AutoMapper throw when mapping null into non-nullable value type?

I have two classes:

public class ClassA
{
    public ClassA(int? value)
    {
        Value = value;
    }

    public int? Value { get; }
}

public class ClassB
{
    public ClassB(int value)
    {
        Value = value;
    }

    public int Value { get; }
}

When mapping an instance of ClassA with Value == null into ClassB, AutoMapper seems to ignore the property and provide the default value instead:

var config = new MapperConfiguration(cfg =>
{
    cfg.CreateMap<ClassA, ClassB>();
});
var mapper = new Mapper(config);

var classA = new ClassA(null);
var classB = mapper.Map<ClassB>(classA);

Debug.Assert(classB.Value == 0);

How do I make AutoMapper throw an exception when mapping an instance of ClassA with Value == null into ClassB instead? Optimally, can I enable this behavior for all mappings from nullable value types to non-nullable value types?

Upvotes: 3

Views: 1813

Answers (2)

Jacob Bundgaard
Jacob Bundgaard

Reputation: 1085

I can create a map from int? to int that throws an exception when the source value is null:

cfg.CreateMap<int?, int>().ConvertUsing((s, _) => s.Value);

However, this requires adding such a map for each nullable value type I want the behavior for.

Upvotes: 1

Jacob Bundgaard
Jacob Bundgaard

Reputation: 1085

I can add a custom BeforeMap function that tries to identify these kind of situations via reflection, but I'd prefer a simpler solution and/or one that also handled custom mappings of differently named properties, etc.

cfg.ForAllMaps((_, e) => e.BeforeMap(CheckForDisallowedNulls));

void CheckForDisallowedNulls(object source, object destination)
{
    foreach (var sourceProperty in source.GetType().GetProperties())
    {
        var underlyingType = Nullable.GetUnderlyingType(sourceProperty.PropertyType);
        if (underlyingType is { })
        {
            var destinationProperty = destination.GetType().GetProperty(sourceProperty.Name);
            if (destinationProperty is { } && destinationProperty.PropertyType == underlyingType && sourceProperty.GetValue(source) == null)
            {
                throw new ArgumentNullException(sourceProperty.Name);
            }
        }
    }
}

Upvotes: 2

Related Questions