How to use Ignore globally in AutoMapper?

2019-07-16 05:02发布

问题:

Here is how it looks like right now. DestinationA and DestinationB are derived from some DestinationBase class. And I need to ignore some common properties for all these derived class. Is there anyway to apply these ignore options globally without having to repeat for all derived destination classes?

Mapper.CreateMap<SourceA, DestinationA>()
      .ForMember(d => d.PropA, opt => opt.Ignore())
      .ForMember(d => d.PropB, opt => opt.Ignore())
      .ForMember(d => d.PropC, opt => opt.Ignore());

Mapper.CreateMap<SourceB, DestinationB>()
      .ForMember(d => d.PropA, opt => opt.Ignore())
      .ForMember(d => d.PropB, opt => opt.Ignore())
      .ForMember(d => d.PropC, opt => opt.Ignore());

I am expecting something like this:

Mapper.CreateMap<DestinationBase>().ForAllSource()
      .ForMember(d => d.PropA, opt => opt.Ignore())
      .ForMember(d => d.PropB, opt => opt.Ignore())
      .ForMember(d => d.PropC, opt => opt.Ignore());

回答1:

There's now a method FindTypeMapFor which makes this extension method even smaller (and more efficient?):

public static IMappingExpression<TSource, TDestination> IgnoreAllNonMapped<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
    {
        foreach (var property in Mapper.FindTypeMapFor<TSource, TDestination>().GetUnmappedPropertyNames())
        {
            expression.ForMember(property, opt => opt.Ignore());
        }
        return expression;
    }


回答2:

I had the same issue and came across this old question while searching for help. I ended up coming up with the following solution. Maybe it's helpful to someone else...

I have several classes derived from a base class. I want to exclude a property of that base class from all mappings of any class that derives from the base. After creating my mappings (and without specifying any ignore options), I do this:

foreach(var map in Mapper.GetAllTypeMaps())
{
    if (typeof(MyBaseClass).IsAssignableFrom(map.DestinationType))
    {
        var propInfo = map.DestinationType.GetProperty("PropertyToIgnore");
        if (propInfo != null) {
            map.FindOrCreatePropertyMapFor(new AutoMapper.Impl.PropertyAccessor(propInfo)).Ignore();
        }
    }
}

It's a little brute force because I have to loop through all the type maps, but it gets the job done.

edit: Added a missing { to the if statement



回答3:

See the IgnoreAllNonExisting() extension by schdr here:
AutoMapper: "Ignore the rest"?

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>()
                .IgnoreAllNonExisting();


回答4:

You can ignore all unmapped properties globally. Although this contradict the main benefit of automapper, allows to make explicit mapping only: This is for Automapper 6:

    var mapperConfiguration = new MapperConfiguration(cfg =>
    {
        cfg.AddProfile(new MyProfile());
        // ignore all unmapped properties globally
        cfg.ForAllMaps((map, exp) => exp.ForAllOtherMembers(opt => opt.Ignore()));
    });