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

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


当前回答

这个问题已经问了几年了,但是这个扩展方法对我来说似乎更干净,使用当前版本的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;
}

其他回答

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

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()来找出哪些属性未映射并自动忽略它们。在我看来这是个更可靠的解决方案。

我知道这是个老问题,但是@jmoerdyk 在你的问题中:

如何在配置文件中的链式creatatemap()表达式中使用它?

你可以像这样在Profile中使用这个答案

this.IgnoreUnmapped();
CreateMap<TSource, Tdestination>(MemberList.Destination)
.ForMember(dest => dest.SomeProp, opt => opt.MapFrom(src => src.OtherProp));

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

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

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

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

你还可以使用:

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

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

这个问题已经问了几年了,但是这个扩展方法对我来说似乎更干净,使用当前版本的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;
}