AutoMapper: "Ignore the rest"?

Solution 1:

From what I understood the question was that there are fields on the destination which doesn't have a mapped field in the source, which is why you are looking for ways to Ignore those non mapped destination fields.

Instead of implementing and using these extension method you could simply use

Mapper.CreateMap<sourceModel, destinationModel>(MemberList.Source);  

Now the automapper knows that it needs to only validate that all the source fields are mapped but not the other way around.

You can also use:

Mapper.CreateMap<sourceModel, destinationModel>(MemberList.Destination);  

Solution 2:

I've updated Can Gencer's extension to not overwrite any existing maps.

public static IMappingExpression<TSource, TDestination> 
    IgnoreAllNonExisting<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
{
    var sourceType = typeof (TSource);
    var destinationType = typeof (TDestination);
    var existingMaps = Mapper.GetAllTypeMaps().First(x => x.SourceType.Equals(sourceType) && x.DestinationType.Equals(destinationType));
    foreach (var property in existingMaps.GetUnmappedPropertyNames())
    {
        expression.ForMember(property, opt => opt.Ignore());
    }
    return expression;
}

Usage:

Mapper.CreateMap<SourceType, DestinationType>()
                .ForMember(prop => x.Property, opt => opt.MapFrom(src => src.OtherProperty))
                .IgnoreAllNonExisting();

Solution 3:

Version 5.0.0-beta-1 of AutoMapper introduces the ForAllOtherMembers extension method so you can now do this:

CreateMap<Source, Destination>()
    .ForMember(d => d.Text, o => o.MapFrom(s => s.Name))
    .ForMember(d => d.Value, o => o.MapFrom(s => s.Id))
    .ForAllOtherMembers(opts => opts.Ignore());

Be aware that there is an advantage to explicitly mapping each property as you will never get problems of mapping failing silently that arise when you forget to map a property.

Perhaps in your case it might be wise to ignore all other members and add a TODO to come back and make these explicit after the frequency of changes to this class settle down.

Solution 4:

This is an extension method I wrote that ignores all non existing properties on the destination. Not sure if it will still be useful as the question is more than two years old, but I ran into the same issue having to add a lot of manual Ignore calls.

public static IMappingExpression<TSource, TDestination> IgnoreAllNonExisting<TSource, TDestination>
(this IMappingExpression<TSource, TDestination> expression)
{
    var flags = BindingFlags.Public | BindingFlags.Instance;
    var sourceType = typeof (TSource);
    var destinationProperties = typeof (TDestination).GetProperties(flags);

    foreach (var property in destinationProperties)
    {
        if (sourceType.GetProperty(property.Name, flags) == null)
        {
            expression.ForMember(property.Name, opt => opt.Ignore());
        }
    }
    return expression;
}

Usage:

Mapper.CreateMap<SourceType, DestinationType>()
                .IgnoreAllNonExisting();

UPDATE: Apparently this does not work correctly if you have custom mappings because it overwrites them. I guess it could still work if call IgnoreAllNonExisting first and then the custom mappings later.

schdr has a solution (as an answer to this question) which uses Mapper.GetAllTypeMaps() to find out which properties are unmapped and auto ignore them. Seems like a more robust solution to me.

Solution 5:

I've been able to do this the following way:

Mapper.CreateMap<SourceType, DestinationType>().ForAllMembers(opt => opt.Ignore());
Mapper.CreateMap<SourceType, DestinationType>().ForMember(/*Do explicit mapping 1 here*/);
Mapper.CreateMap<SourceType, DestinationType>().ForMember(/*Do explicit mapping 2 here*/);
...

Note: I'm using AutoMapper v.2.0.