有没有一种方法告诉AutoMapper忽略所有的属性,除了那些显式映射的?

我有可能从外部更改的外部DTO类,并且我希望避免显式地指定要忽略的每个属性,因为添加新属性将在尝试将它们映射到自己的对象时破坏功能(导致异常)。


当前回答

在dotnet 5的WebApi中,使用Nuget包automapper . extensions .微软。DependencyInjection,我在一个映射器配置文件中这样做。我对AutoMapper真的生疏了,但它现在似乎对未映射的成员工作得很好。

在启动:

var mapperConfig = new MapperConfiguration(mc => mc.AddProfile(new AutoMapperProfile()));
    services.AddSingleton(mapperConfig.CreateMapper());

在我的AutoMapperProfile中:

CreateMap<ProjectActivity, Activity>()
        .ForMember(dest => dest.ActivityName, opt => opt.MapFrom(src => src.Name))
        .ValidateMemberList(MemberList.None);

其他回答

您希望如何指定忽略某些成员?是否有您想要应用的约定、基类或属性?一旦您开始显式地指定所有映射,我不确定您能从AutoMapper中得到什么价值。

在3.3.1版本中,您可以使用IgnoreAllPropertiesWithAnInaccessibleSetter()或IgnoreAllSourcePropertiesWithAnInaccessibleSetter()方法。

我更新了Robert Schroeder对AutoMapper 4.2的答案。对于非静态映射器配置,我们不能使用mapper . getalltypemaps(),但表达式有一个对所需的TypeMap的引用:

public static IMappingExpression<TSource, TDestination> 
    IgnoreAllNonExisting<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
{
    foreach (var property in expression.TypeMap.GetUnmappedPropertyNames())
    {
        expression.ForMember(property, opt => opt.Ignore());
    }
    return expression;
}

更新:这个答案对那些使用最新版本的Automapper不再有用,因为ForAllOtherMembers已经在Automapper 11中被删除了。


AutoMapper的5.0.0-beta-1版本引入了ForAllOtherMembers扩展方法,所以你现在可以这样做:

CreateMap<Source, Destination>()
    .ForMember(d => d.Text, o => o.MapFrom(s => s.Name))
    .ForMember(d => d.Value, o => o.MapFrom(s => s.Id))
    .ForAllOtherMembers(opts => opts.Ignore());

请注意,显式映射每个属性有一个好处,因为当您忘记映射某个属性时,您永远不会遇到映射失败的问题。

也许在您的情况下,明智的做法是忽略所有其他成员,并添加一个TODO来返回,并在该类的更改频率稳定下来后显式地显示这些成员。

我已经更新了Can Gencer的扩展,不覆盖任何现有的地图。

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

用法:

Mapper.CreateMap<SourceType, DestinationType>()
                .ForMember(prop => x.Property, opt => opt.MapFrom(src => src.OtherProperty))
                .IgnoreAllNonExisting();

更新:注意,在9.0版本Mapper静态API被删除