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

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


当前回答

更新:这个答案对那些使用最新版本的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来返回,并在该类的更改频率稳定下来后显式地显示这些成员。

其他回答

根据我的理解,这个问题是,目标上的字段在源中没有映射字段,这就是为什么您要寻找方法来忽略那些非映射的目标字段。

而不是实现和使用这些扩展方法,您可以简单地使用

Mapper.CreateMap<sourceModel, destinationModel>(MemberList.Source);  

现在,automapper知道它只需要验证所有源字段都映射了,而不是相反。

你还可以使用:

Mapper.CreateMap<sourceModel, destinationModel>(MemberList.Destination);  

这个问题已经问了几年了,但是这个扩展方法对我来说似乎更干净,使用当前版本的AutoMapper (3.2.1):

public static IMappingExpression<TSource, TDestination> IgnoreUnmappedProperties<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
{
    var typeMap = Mapper.FindTypeMapFor<TSource, TDestination>();
    if (typeMap != null)
    {
        foreach (var unmappedPropertyName in typeMap.GetUnmappedPropertyNames())
        {
            expression.ForMember(unmappedPropertyName, opt => opt.Ignore());
        }
    }

    return expression;
}

您可以使用ForAllMembers,而不是只覆盖所需 像这样

public static IMappingExpression<TSource, TDest> IgnoreAll<TSource, TDest>(this IMappingExpression<TSource, TDest> expression)
        {
            expression.ForAllMembers(opt => opt.Ignore());
            return expression;
        }

小心,它将忽略所有,如果你不添加自定义映射,它们已经被忽略,将无法工作

我还想说,如果你有AutoMapper的单元测试。你测试了所有的模型,所有的属性映射正确,你不应该使用这种扩展方法

你应该显式地写ignore

从AutoMapper 5.0开始,IMappingExpression上的. typemap属性消失了,这意味着4.2解决方案不再有效。我已经创建了一个解决方案,使用原始功能,但具有不同的语法:

var config = new MapperConfiguration(cfg =>
{
    cfg.CreateMap<Src, Dest>();
    cfg.IgnoreUnmapped();        // Ignores unmapped properties on all maps
    cfg.IgnoreUnmapped<Src, Dest>();  // Ignores unmapped properties on specific map
});

// or add  inside a profile
public class MyProfile : Profile
{
   this.IgnoreUnmapped();
   CreateMap<MyType1, MyType2>();
}

实现:

public static class MapperExtensions
{
    private static void IgnoreUnmappedProperties(TypeMap map, IMappingExpression expr)
    {
        foreach (string propName in map.GetUnmappedPropertyNames())
        {
            if (map.SourceType.GetProperty(propName) != null)
            {
                expr.ForSourceMember(propName, opt => opt.Ignore());
            }
            if (map.DestinationType.GetProperty(propName) != null)
            {
                expr.ForMember(propName, opt => opt.Ignore());
            }
        }
    }

    public static void IgnoreUnmapped(this IProfileExpression profile)
    {
        profile.ForAllMaps(IgnoreUnmappedProperties);
    }

    public static void IgnoreUnmapped(this IProfileExpression profile, Func<TypeMap, bool> filter)
    {
        profile.ForAllMaps((map, expr) =>
        {
            if (filter(map))
            {
                IgnoreUnmappedProperties(map, expr);
            }
        });
    }

    public static void IgnoreUnmapped(this IProfileExpression profile, Type src, Type dest)
    {
        profile.IgnoreUnmapped((TypeMap map) => map.SourceType == src && map.DestinationType == dest);
    }

    public static void IgnoreUnmapped<TSrc, TDest>(this IProfileExpression profile)
    {
        profile.IgnoreUnmapped(typeof(TSrc), typeof(TDest));
    }
}

版本12 这是一个非常糟糕的代码,但它解决了紧急工作。

      CreateMap<RepairPutRequest, Repair>(MemberList.None) 
                .ForAbdusselamMember(x => x.ClosedLostTimeId, y => y.MapFrom(z => z.ClosedLostTimeId))
                .ForAbdusselamMember(x => x.Explanation, y => y.MapFrom(z => z.Explanation)).IgnoreUnmapped()
                ; 
  public static class MappingExtensions
    {
        public static Dictionary<string, List<string>> list = new Dictionary<string, List<string>>();
        public static IMappingExpression<TSource, TDestination> IgnoreUnmapped<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
        {
             var sourceType = typeof(TSource);
            var destinationType = typeof(TDestination);
            var key =$"{sourceType.FullName}__||__{destinationType.FullName}"   ;
            var t = list[key];
            foreach (var item in destinationType.GetProperties())
            {
                if (!t.Contains(item.Name)) {
                    expression.ForMember(item.Name, x => x.Ignore());
                    }
            }
            return expression;
        }
        public static IMappingExpression<TSource, TDestination> ForAbdusselamMember<TSource, TDestination, TMember>(this IMappingExpression<TSource, TDestination> expression,
            Expression<Func<TDestination, TMember>> destinationMember, Action<IMemberConfigurationExpression<TSource, TDestination, TMember>> memberOptions )
        {
            var sourceType = typeof(TSource);
            var destinationType = typeof(TDestination);
            var key = $"{sourceType.FullName}__||__{destinationType.FullName}";
            if (!list.ContainsKey(key))
            {
                list[key]=new List<string>();
            }
            expression.ForMember(destinationMember, memberOptions);
            var memberInfo = ReflectionHelper.FindProperty(destinationMember);

            list[key].Add(memberInfo.Name);
            return expression;
        }
          
    }