自动映射器-忽略IEnumerable< SelectListItem>的所有项目. [英] Automapper - ignore all items of IEnumerable<SelectListItem>
问题描述
Automapper是否仍然会忽略某个类型的所有属性?我们正在尝试通过验证Automapper映射来提高代码质量,但必须为始终手动创建的所有IEnumerable<SelectListItem>
放置.Ignore()
会产生摩擦并减慢开发速度.
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.
有什么想法吗?
创建映射后可能的想法:
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 there is three ways to ignore properties:
-
在创建映射时使用
Ignore()
选项
Mapper.CreateMap<Source, Dest>()
.ForMember(d => d.IgnoreMe, opt => opt.Ignore());
这就是您要避免的事情.
this is what you want to avoid.
使用IgnoreMapAttribute
如果您的IEnumerable<SelectListItem>
属性名称遵循某些命名约定.例如.它们都以"Select"
开头,您可以使用AddGlobalIgnore
方法来全局忽略它们:
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.
但是,您可以为第一个选项创建一个便利扩展方法,当您调用CreateMap
时,该方法将自动忽略给定类型的属性:
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.
如果您不怕弄脏自己的手,
当前有一个非常棘手的解决方案,它深入到Automapper的内部.我不知道此API的公开程度,因此该解决方案可能会削弱该功能:
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:
您可以订阅ConfigurationStore
的TypeMapCreated
事件
((ConfigurationStore)Mapper.Configuration).TypeMapCreated += OnTypeMapCreated;
并直接在创建的TypeMap
实例上添加基于类型的忽略:
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();
}
}
}
这篇关于自动映射器-忽略IEnumerable< SelectListItem>的所有项目.的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!