3

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());
abatishchev
  • 98,240
  • 88
  • 296
  • 433
gdenuf
  • 840
  • 1
  • 12
  • 16

5 Answers5

3

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()));
    });
Dmitry
  • 31
  • 2
2

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;
    }
Eli Algranti
  • 8,707
  • 2
  • 42
  • 50
  • Automapper 8 dosn't contain FindTypeMapFor seems like AM is evolving so fast all answers are useless. I'm getting a feeling AutoMapper is becoming useless – Pawel Cioch Jun 04 '19 at 21:19
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

Jon Dosmann
  • 667
  • 7
  • 20
John
  • 1,186
  • 10
  • 9
0

I'm not sure which version added attributes, but these days you can do this. Docs.

[Ignore]
public string Property { get; set; }

Problem with that approach is you leak AutoMapper implementation across domain entities, which isn't great.

A better approach seems to be to setup filtering on the MapperConfiguration globally, by defining your own ShouldMapProperty delegate, or tacking on a condition to the default implementation. Docs.

var configuration = new MapperConfiguration(cfg =>
{
    cfg.ShouldMapField = ...;

    cfg.ShouldMapProperty = ...;
});

The default implementations at time of writing are here. Notably, ShouldMapProperty falls back if not specified to p => p.IsPublic(). So you could do p => p.IsPublic() && p.DeclaringType != typeof(SomeBaseType) && p.Name == nameof(SomeBaseType.SomePropertyToIgnore).

benmccallum
  • 1,241
  • 12
  • 27
0

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();
Community
  • 1
  • 1
Rami A.
  • 10,302
  • 4
  • 44
  • 87
  • Thanks, Rami. That helps. But i would still consider it dangerous as It ignores not only the properties you define but everything not mapped. Maybe i will have to tweak this a little bit. Thanks – gdenuf Dec 30 '11 at 03:09
  • @Nay yeah I did a similar thing, where we logged silently any values in product, we let it break on our local build. – Anicho Jun 17 '13 at 16:37