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

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


当前回答

这是我编写的一个扩展方法,它忽略目标上所有不存在的属性。不确定它是否仍然有用,因为这个问题已经存在两年多了,但我遇到了同样的问题,必须添加大量手动忽略调用。

public static IMappingExpression<TSource, TDestination> IgnoreAllNonExisting<TSource, TDestination>
(this IMappingExpression<TSource, TDestination> expression)
{
    var flags = BindingFlags.Public | BindingFlags.Instance;
    var sourceType = typeof (TSource);
    var destinationProperties = typeof (TDestination).GetProperties(flags);

    foreach (var property in destinationProperties)
    {
        if (sourceType.GetProperty(property.Name, flags) == null)
        {
            expression.ForMember(property.Name, opt => opt.Ignore());
        }
    }
    return expression;
}

用法:

Mapper.CreateMap<SourceType, DestinationType>()
                .IgnoreAllNonExisting();

更新:显然,如果您有自定义映射,这不能正确工作,因为它会覆盖它们。我想如果先调用IgnoreAllNonExisting,然后再调用自定义映射,它仍然可以工作。

schdr有一个解决方案(作为这个问题的答案),它使用map . getalltypemaps()来找出哪些属性未映射并自动忽略它们。在我看来这是个更可靠的解决方案。

其他回答

默认情况下,AutoMapper使用目标类型来验证成员,但您可以通过使用MemberList跳过验证。没有选择。

var configuration = new MapperConfiguration(cfg =>
  cfg.CreateMap<Source2, Destination2>(MemberList.None);
);

你可以在这里找到参考资料

我已经能够做到这一点的方式如下:

Mapper.CreateMap<SourceType, DestinationType>().ForAllMembers(opt => opt.Ignore());
Mapper.CreateMap<SourceType, DestinationType>().ForMember(/*Do explicit mapping 1 here*/);
Mapper.CreateMap<SourceType, DestinationType>().ForMember(/*Do explicit mapping 2 here*/);
...

注意:我使用的是AutoMapper v.2.0。

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

对于那些使用4.2.0及以上版本的非静态API的人,可以使用以下扩展方法(在AutoMapperExtensions类中找到):

// from http://stackoverflow.com/questions/954480/automapper-ignore-the-rest/6474397#6474397
public static IMappingExpression IgnoreAllNonExisting(this IMappingExpression expression)
{
    foreach(var property in expression.TypeMap.GetUnmappedPropertyNames())
    {
        expression.ForMember(property, opt => opt.Ignore());
    }
    return expression;
}

这里重要的是,一旦删除了静态API,像Mapper这样的代码。FindTypeMapFor将不再工作,因此要使用表达式。TypeMap字段。

The only infromation about ignoring many of members is this thread - http://groups.google.com/group/automapper-users/browse_thread/thread/9928ce9f2ffa641f . I think you can use the trick used in ProvidingCommonBaseClassConfiguration to ignore common properties for similar classes. And there is no information about the "Ignore the rest" functionality. I've looked at the code before and it seems to me that will be very and very hard to add such functionality. Also you can try to use some attribute and mark with it ignored properties and add some generic/common code to ignore all marked properties.