12

是否有 Automapper 忽略某种类型的所有属性?我们试图通过验证 Automapper 映射来提高代码的质量,但是必须.Ignore()为所有IEnumerable<SelectListItem>总是手动创建的东西添加一个会产生摩擦并减慢开发速度。

有任何想法吗?

创建映射后可能的想法:

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

2 回答 2

18

Automapper 当前不支持基于类型的属性忽略。

目前有三种方法可以忽略属性:

  • Ignore()创建映射时使用选项

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

    这是您要避免的。

  • IEnumerable<SelectListItem>用_IgnoreMapAttribute

  • 如果您的IEnumerable<SelectListItem>属性名称遵循一些命名约定。例如,它们都以单词开头,"Select"您可以使用该AddGlobalIgnore方法全局忽略它们:

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

    但是有了这个,你只能匹配以开头。

但是,您可以为第一个选项创建一个方便的扩展方法,它会在您调用时自动忽略给定类型的属性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;
    }
}

您可以通过以下方式使用它:

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

所以它仍然不是一个全局解决方案,但您不必列出需要忽略哪些属性,它适用于同一类型的多个属性。

如果你不怕弄脏你的手:

目前有一个非常 hacky 的解决方案,它深入到 Automapper 的内部。我不知道这个 API 的公开程度如何,所以这个解决方案可能会阻碍这个功能:

您可以订阅ConfigurationStore'sTypeMapCreated事件

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

并直接在创建的TypeMap实例上添加基于类型的忽略:

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();
        }
    }
}
于 2013-03-11T13:03:39.390 回答
1

如果你现在遇到这个,似乎还有另一种方法。

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

我没有调查这个是什么时候引入的。这似乎会阻止或允许您过滤它。看到这个:AutoMapper 配置

于 2017-11-30T03:54:59.573 回答