3

I'm defining a mapping between a source class and a target class:

Mapper.CreateMap<Source, Target>();

I want the mapping to return null if a certain property on the Source is set to a particular value:

// If Source.IsValid = false I want the mapping to return null
Source s = new Source { IsValid = false };
Target t = Mapper.Map<Target>(s);
Assert.IsNull(t);

How do I configure AutoMapper to achieve that?

9
  • I don't have a direct answer, but I can see some problems. Firstly, automapper does not support calculated property on a domain object. Whether your NULL case meets that condition is something you have to explore further. In general, automapper uses LINQ's logic for NULL, which may not operate the way you want with a boolean value. I've seen only nullable INT values in LINQ. It appears you can implement your NULL logic after the mapping step has been completed. Intercepting mapping with custom NULL logic seems needless complexity. Commented Jun 24, 2015 at 2:24
  • @EmacsUser thank you for your comment. Parsing the whole object tree again, after AutoMapper already did this to implement custom NULL logic does seem needless complexity. It would be nice if there would be a way to let AutoMapper know that we need this logic so that it could plug it in. Commented Jun 24, 2015 at 2:30
  • 2
    I think with nullable prop you can do something like that. Mapper.CreateMap<Source, Target>().ForMember(dest => dest.Prop, opt => opt.MapFrom(src => src.Prop ==1 ? src.Prop: null)); Commented Jun 24, 2015 at 2:32
  • @zespri, you should contact them directly, I don't work for them. Commented Jun 24, 2015 at 2:32
  • @AndréMendonça, well that will set a property to null, I need the whole object to be null. Commented Jun 24, 2015 at 2:37

2 Answers 2

3

You can define your mapping like this:

Mapper.CreateMap<Source, Target>().TypeMap
  .SetCondition(r => ((Source)r.SourceValue).IsValid);
Sign up to request clarification or add additional context in comments.

5 Comments

This is even simpler, however you lose the ability to map the component is if it null, don't you? Anyway, thanks for the alternative, I didn't know you could go and change the mapping after it had been defined.
Indeed, but changing the constructor and then trying to map the destination will throw a null reference exception, you can try this to see var mapping = Mapper.CreateMap<From, To>() .ForMember(to => to.DestinationName, opt => opt.MapFrom(from => from.Active ? from.Name : (string)null)); mapping.TypeMap.DestinationCtor = r => ((From)r.SourceValue).Active ? new To() : null; WriteMappedFrom(new From() { Active = false, Name = "InactiveFrom" }); // this fails
@samy you are right. I updated the answer, will this hold up?
This works fine in my test pad, and is more elegant than my solution which is a bit clunky
@samy I like yours though, because it demonstrated a useful technique I did not know. Thanks again!
1

EDIT

If you want your map to output a null object I'd recommend using two levels of mapping: the first level decides whether or not to return a null object by taking over mapping behavior with the ConvertUsing method, and if mapping is required it defers it to an inner mapping engine:

static void Main(string[] args)
{
    var innerConfigurationStore = new ConfigurationStore(new TypeMapFactory(), MapperRegistry.Mappers);
    innerConfigurationStore.CreateMap<From, To>()
                .ForMember(to => to.DestinationName, opt => opt.MapFrom(from => from.Active ? from.Name : (string)null));
    var innerMappingEngine = new MappingEngine(innerConfigurationStore);

    Mapper.CreateMap<From, To>()
        .ConvertUsing(from => from.Active ? innerMappingEngine.Map<To>(from) : null)
        ;

    WriteMappedFrom(new From() {Active = true, Name = "ActiveFrom"});
    WriteMappedFrom(new From() {Active = false, Name = "InactiveFrom"});
}

static void WriteMappedFrom(From from)
{
    Console.WriteLine("Mapping from " + (from.Active ? "active" : "inactive") + " " + from.Name);
    var to = Mapper.Map<To>(from);
    Console.WriteLine("To -> " + (to == null ? "null" :  "not null"));
}

INITIAL ANSWER

It's quite simple to use a conditional mapping in Automapper, here is some sample code

public class From
{
    public bool Active { get; set; }
    public string Name { get; set; }
}

public class To
{
    public string DestinationName { get; set; }
}
static void Main(string[] args)
{
    Mapper.CreateMap<From, To>()
        .ForMember(to => to.DestinationName, opt => opt.MapFrom(from => from.Active ? from.Name : (string)null));

    WriteMappedFrom(new From() {Active = true, Name = "ActiveFrom"});
    WriteMappedFrom(new From() {Active = false, Name = "InactiveFrom"});
}

static void WriteMappedFrom(From from)
{
    Console.WriteLine("Mapping from " + (from.Active ? "active" : "inactive") + " " + from.Name);
    var to = Mapper.Map<To>(from);
    Console.WriteLine("To -> " + (to.DestinationName ?? "null"));
}

There are other conditional mappings in automapper but they seem to work only on convention-based mappings. You could however look into the documentation a bit more to confirm

2 Comments

I'd like to set the whole object to null, not just a property
This certainly works. Thank you very much. Special thanks for a complete example. While waiting for an answer I've stumbled upon another solution that I'll post shortly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.