Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automapper - ignore all items of IEnumerable<SelectListItem>

Tags:

automapper

Is there anyway of Automapper to ignore all properties of a certain type? We are trying to improve the quality of our code by validating the Automapper mappings but having to put an .Ignore() for all IEnumerable<SelectListItem> which are always manually created is creating friction and slowing down development.

Any ideas?

Possible Idea after creating mappings:

    var existingMaps = Mapper.GetAllTypeMaps();
    foreach (var property in existingMaps)
    {
        foreach (var propertyInfo in property.DestinationType.GetProperties())
        {
            if (propertyInfo.PropertyType == typeof(List<SelectListItem>) || propertyInfo.PropertyType == typeof(IEnumerable<SelectListItem>))
            {
                property.FindOrCreatePropertyMapFor(new PropertyAccessor(propertyInfo)).Ignore();
            }
        }
    }
like image 284
GraemeMiller Avatar asked Mar 11 '13 11:03

GraemeMiller


2 Answers

If you come across this now, it appears there is another way.

Mapper.Initialize(cfg =>
{
    cfg.ShouldMapProperty = pi => pi.PropertyType != typeof(ICommand);
});

I did not look into when this was introduced. This appears it will block or allow for however you filter this. See this: AutoMapper Configuration

like image 173
Chris Culver Avatar answered Nov 10 '22 00:11

Chris Culver


Automapper currently does not support type based property ignores.

Currently there is three ways to ignore properties:

  • Use the Ignore() options when creating your mapping

    Mapper.CreateMap<Source, Dest>()
        .ForMember(d => d.IgnoreMe, opt => opt.Ignore());
    

    this is what you want to avoid.

  • Annotate on the your IEnumerable<SelectListItem> properties with the the IgnoreMapAttribute

  • If your IEnumerable<SelectListItem> property names follow some naming convention. E.g. all them start with the word "Select" you can use the AddGlobalIgnore method to ignore them globally:

    Mapper.Initialize(c => c.AddGlobalIgnore("Select"));
    

    but with this you can only match with starts with.

However you can create a convinience extension method for the first options which will automatically ignore the properties of a given type when you call CreateMap:

public static class MappingExpressionExtensions
{
    public static IMappingExpression<TSource, TDest> 
        IgnorePropertiesOfType<TSource, TDest>(
        this IMappingExpression<TSource, TDest> mappingExpression,
        Type typeToIgnore
        )
    {
        var destInfo = new TypeInfo(typeof(TDest));
        foreach (var destProperty in destInfo.GetPublicWriteAccessors()
            .OfType<PropertyInfo>()
            .Where(p => p.PropertyType == typeToIgnore))
        {
            mappingExpression = mappingExpression
                .ForMember(destProperty.Name, opt => opt.Ignore());
        }

        return mappingExpression;
    }
}

And you can use it with the following way:

Mapper.CreateMap<Source, Dest>()
    .IgnorePropertiesOfType(typeof(IEnumerable<SelectListItem>));

So it still won't be a global solution, but you don't have to list which properties need to be ignored and it works for multiple properties on the same type.

If you don't afraid to get your hands dirty:

There is currently a very hacky solution which goes quite deep into the internals of Automapper. I don't know how public is this API so this solution might brake in the feature:

You can subscribe on the ConfigurationStore's TypeMapCreated event

((ConfigurationStore)Mapper.Configuration).TypeMapCreated += OnTypeMapCreated;

and add the type based ignore directly on the created TypeMap instances:

private void OnTypeMapCreated(object sender, TypeMapCreatedEventArgs e)
{
    foreach (var propertyInfo in e.TypeMap.DestinationType.GetProperties())
    {
        if (propertyInfo.PropertyType == typeof (IEnumerable<SelectListItem>))
        {
            e.TypeMap.FindOrCreatePropertyMapFor(
                new PropertyAccessor(propertyInfo)).Ignore();
        }
    }
}
like image 30
nemesv Avatar answered Nov 09 '22 22:11

nemesv