Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automapper conditional map from multiple source fields

Tags:

c#

automapper

I've got a source class like the following:

public class Source
{
    public Field[] Fields { get; set; }
    public Result[] Results { get; set; }
}

And have a destination class like:

public class Destination
{
    public Value[] Values { get; set; }
}

So I want to map from EITHER Fields or Results to Values depending on which one is not null (only one will ever have a value).

I tried the following map:

CreateMap<Fields, Values>();                
CreateMap<Results, Values>();                

CreateMap<Source, Destination>()                
            .ForMember(d => d.Values, opt =>
            {
                opt.PreCondition(s => s.Fields != null);
                opt.MapFrom(s => s.Fields });
            })
            .ForMember(d => d.Values, opt =>
            {
                opt.PreCondition(s => s.Results != null);
                opt.MapFrom(s => s.Results);
            });

Only issue with this is that it looks if the last .ForMember map doesn't meet the condition it wipes out the mapping result from the first map.

I also thought about doing it as a conditional operator:

opt => opt.MapFrom(s => s.Fields != null ? s.Fields : s.Results)

But obviously they are different types so don't compile.

How can I map to a single property from source properties of different types based on a condition?

Thanks

like image 307
ADringer Avatar asked Dec 24 '22 16:12

ADringer


1 Answers

There is a ResolveUsing() method that allows you for more complex binding and you can use a IValueResolver or a Func. Something like this:

CreateMap<Source, Destination>()
    .ForMember(dest => dest.Values, mo => mo.ResolveUsing<ConditionalSourceValueResolver>());

And the value resolver depending on your needs may look like:

 public class ConditionalSourceValueResolver : IValueResolver<Source, Destination, Value[]>
    {
        public Value[] Resolve(Source source, Destination destination, Value[] destMember, ResolutionContext context)
        {
            if (source.Fields == null)
                return context.Mapper.Map<Value[]>(source.Results);
            else
                return context.Mapper.Map<Value[]>(source.Fields);
        }
    }
like image 51
animalito maquina Avatar answered Jan 05 '23 00:01

animalito maquina