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();
}
}
}
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();
}
}
}
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