AutoMapper Map If Not Null, Otherwise Custom Convert

Here's my code:

Mapper.CreateMap<Foo, Foo2>()
   .ForMember(dest => dest.Bar, opt => opt.MapFrom(src => src.Bar == null ? new BarViewModel() : src.Bar))

Basically, "BarViewModel" has a parameterless ctor which sets up properties in the class.

So i'm trying to say to AutoMapper:

If the value is null, then use the ctor for the class. otherwise use the mapping you have in place

The above is giving me a C# compiler error. And i'm guessing a cast wouldn't work either.

So is there a AutoMapper trick to do this?

Worst case i could remove that mapping for that property, and just do:

var mapped = Mapper.Map<Foo,Foo2>(src);
if (mapped.Bar == null) mapped.Bar = new BarViewModel();

But that's a tad ugly.

Ideas?

Answers


You can use custom value resolver. The following should work:

Mapper.CreateMap<Foo, Foo2>()
   .ForMember(dest => dest.Bar, opt => opt.ResolveUsing(src => src.Bar == null ? new Bar() : Mapper.Map<Bar,Bar2>(src.Bar)))

Now you can use .NullSubstitute() to replace NULL value to some custom value in Automapper, e.g.:

CreateMap<SMModel, VM_SMModel>()
                    .ForMember(d => d.myDate, o => o.NullSubstitute(new DateTime(2017,12,12)));

I don't get a compiler error for the following:

public class Foo
{
    public Bar Bar { get; set; }
}

public class Foo2
{
    public Bar Bar { get; set; }
}

public class Bar
{
    public int Id { get; set; }

    public Bar()
    {
        Id = 3;
    }
}

CreateMap<Foo, Foo2>()
    .ForMember(
        dest => dest.Bar,
        opt => opt.MapFrom(src => src.Bar == null ? new Bar() : src.Bar));

...so I'm wondering if the problem is not actually with your mapping?


As of Automapper 8, ResolveUsing is no longer an option but inline Func's, IValueResolver and IMemberValueResolver are 😊.

Inline Func Example

Mapper.Initialize(cfg =>
{
    cfg.CreateMap<Foo, FooViewModel>()
       .ForMember(dest => dest.BarViewModel,
                  opt  => opt.MapFrom((src, dest) =>
                  {
                     if (src.Bar == null)
                        return new BarViewModel ();

                     return Mapper.Map<Bar, BarViewModel>(src.Bar);
                  }));

    cfg.CreateMap<Bar, BarViewModel>();
});

IMemberValueResolver Example

Mapper.Initialize(cfg =>
{
    cfg.CreateMap<Foo, FooViewModel>()
       .ForMember(dest => dest.BarViewModel,
                  opt  => opt.MapFrom<NullBarResolver, Bar>(src => src.Bar));

    cfg.CreateMap<Bar, BarViewModel>();
});

public class NullBarResolver : IMemberValueResolver<object, object, Bar, BarViewModel>
{
    public BarViewModel Resolve(object source, object destination, Bar sourceMember,
                                BarViewModel destMember, ResolutionContext context)
    {
        if (sourceMember == null)
            return new BarViewModel();

        return Mapper.Map(sourceMember, destMember);
    }
}

There's some good documentation on Custom Value Resolvers here.

Working demo


Need Your Help

Options for HTML scraping?

html web-scraping html-parsing html-content-extraction

I'm thinking of trying Beautiful Soup, a Python package for HTML scraping. Are there any other HTML scraping packages I should be looking at? Python is not a requirement, I'm actually interested in

What is difference among styles.xml and themes.xml

android android-theme android-styles

May I know what is the difference between styles.xml and themes.xml? To me, they just look same as both XML are in the same format.