忽略使用Automapper映射一个属性


285

我正在使用Automapper,并且有以下情况:类OrderModel具有一个不在数据库中的名为“ ProductName”的属性。因此,当我尝试使用以下方法进行映射时:

Mapper.CreateMap<OrderModel, Orders>(); 

它产生一个异常:

“未映射Project.ViewModels.OrderModel上的以下1个属性:'ProductName'

我已经在AutoMapper的Wiki for Projections中阅读了相反的情况(多余的属性在目标上,而不是在源中,这实际上是我的情况)

如何避免自动映射器对此属性进行映射?


7
Automapper不能那样工作。它只关心目标对象上的属性。src可以包含100个额外的属性-Automapper仅映射dest属性。肯定有其他原因导致映射异常。您可以张贴一些无效的代码吗?
PatrickSteele 2010年

它会自动执行您的要求。发布一些代码进行澄清
BeRecursive


3
@Patrick AutoMapper在分析方法/属性名称方面有一些技巧。即使目标上不存在完全匹配的内容,源上仍有可能被无意映射的属性。这就是为什么有一个ForSourceMember(... Ignore())防止这种情况发生的原因。
AaronLS 2012年

Answers:


477

从吉米·博加德(Jimmy Bogard): CreateMap<Foo, Bar>().ForMember(x => x.Blarg, opt => opt.Ignore());

这是他博客中的评论之一


13
另外,CreateMap<Foo, Bar>().ForSourceMember(x => x.Blarg, opt => opt.Ignore());可能会有用
stackoverfloweth

5
@stackoverfloweth您的意思不是CreateMap<SourceType, DestType> (MemberList.Source).ForSourceMember(x => x.MySourceProperty, opt => opt.DoNotValidate())吗?
monty

12
在ForSourceMember中,忽略已被DoNotValidate取代:github.com/AutoMapper/AutoMapper/blob/master/docs/…–
Jamie,

@Jamie @monty-我开始更新此内容:您的评论,但看起来语法更改仅影响投影的大小写(需要忽略source属性)。OP的请求是忽略目标属性,因此Ignore()保留正确的语法。这是因为的语法更改Ignore是在ISourceMemberConfigurationExpression接口上进行的,而不是在不相交的IMemberConfigurationExpression`3接口上进行的。
smartcaveman

2
@Franva ForMember()实际上是“ ForDestinationMember()”
rvnlord

243

我也许是个完美主义者。我不太喜欢ForMember(...,x => x.Ignore())语法。这是小事,但对我来说很重要。我写了这个扩展方法,使它更好一点:

public static IMappingExpression<TSource, TDestination> Ignore<TSource, TDestination>(
    this IMappingExpression<TSource, TDestination> map,
    Expression<Func<TDestination, object>> selector)
{
    map.ForMember(selector, config => config.Ignore());
    return map;
}

可以这样使用:

Mapper.CreateMap<JsonRecord, DatabaseRecord>()
        .Ignore(record => record.Field)
        .Ignore(record => record.AnotherField)
        .Ignore(record => record.Etc);

您也可以重写它以与 params,但我不喜欢带有大量lambda的方法的外观。


6
我知道这超出了最初的问题,但我真的很喜欢这个答案,它干净,非常易于阅读,可以立即理解并且易于重用
Lski 2014年

关于params:您可以从一个lambda内部返回一个选择器数组,然后以foreachSelect()看起来不太混乱的方式映射到每个选择器。
jpaugh

感谢@Steve Rukuts,对于正在寻找扩展方法以忽略源成员的任何人,您可以使用此公共静态IMappingExpression <TSource,TDestination> IgnoreSourceValidation <TSource,TDestination>(此IMappingExpression <TSource,TDestination>映射,Expression <Func <TSource ,object >>选择器){map.ForSourceMember(selector,config => config.DoNotValidate()); 返回地图 }
杰森·迪亚斯

79

你可以这样做:

conf.CreateMap<SourceType, DestinationType>()
   .ForSourceMember(x => x.SourceProperty, y => y.Ignore());

自动映射器是否具有ForSourceMember扩展?
兑换了2012年

我目前正在这样做,但是理想的情况是不必创建所有这些忽略项::/
Tom Stickel

您知道在实际进行映射时是否有一种方法可以忽略,而在创建地图时是否可以忽略?
山姆,我说恢复莫妮卡2014年


3
对于问题中给出的方案,这应该是公认的答案。当前接受的答案将忽略目标对象中属性的映射。这个问题是关于忽略源对象中的映射的问题。
Rob S.

28

仅对于尝试自动执行此操作的任何人,您都可以使用该扩展方法来忽略目标类型上不存在的属性:

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>().IgnoreAllNonExisting();

感谢Can Gencer的提示:)

来源:http : //cangencer.wordpress.com/2011/06/08/auto-ignore-non-existing-properties-with-automapper/



1
注入IMapper时,这不起作用。最新版本的AutoMapper中不存在Mapper.GetAllTypeMaps。此外,当我在AutoMapper.Profile中设置地图并随后注入IMapper时,出现此异常“ Mapper未初始化。请使用适当的配置调用Initialize。如果您尝试通过容器或其他方式使用Mapper实例,请确保没有对静态Mapper.Map方法的任何调用,并且如果您使用的是ProjectTo或UseAsDataSource扩展方法,请确保传递适当的IConfigurationProvider实例。”
Ristogod

我刚得到'Mapper' does not contain a definition for 'GetAllTypeMaps' [DSSTools]..
Bassie

2
@Bassie使用Mapper.Configuration.GetAllTypeMaps() 来源
Mike Bovenlander

28

现在有一个(AutoMapper 2.0)IgnoreMap属性,我将使用它,而不是流利的语法,恕我直言。


35
尽管如此,ignore属性会通过您的应用程序泄漏自动映射器。
Phill

11
AutoMapper是一件事,我不介意到处泄漏。;)
Pawel Krakowiak 2012年

4
您可以随时考虑推导IgnoreMapAttribute
Alapago

1
这是忽略跨许多对象继承的基本属性的好方法。不必在每个映射配置中都忽略它。
Chase Florell '18

23

将视图模型映射回域模型时,仅验证源成员列表而不是目标成员列表可以更加简洁。

Mapper.CreateMap<OrderModel, Orders>(MemberList.Source); 

现在Ignore(),每次将属性添加到域类时,映射验证都不会失败,需要另一个验证。


7
这就是我要寻找的,当仅从更简单的DTO修改域对象属性的子集时非常有用。
亚当·托利

5
这是孩子们的答案,请确保官员不让新手感到困惑
Piotr M


-5

大家好,请使用它,它工作正常...对于自动映射器,在C#中 使用多个.ForMember

        if (promotionCode.Any())
        {
            Mapper.Reset();
            Mapper.CreateMap<PromotionCode, PromotionCodeEntity>().ForMember(d => d.serverTime, o => o.MapFrom(s => s.promotionCodeId == null ? "date" : String.Format("{0:dd/MM/yyyy h:mm:ss tt}", DateTime.UtcNow.AddHours(7.0))))
                .ForMember(d => d.day, p => p.MapFrom(s => s.code != "" ? LeftTime(Convert.ToInt32(s.quantity), Convert.ToString(s.expiryDate), Convert.ToString(DateTime.UtcNow.AddHours(7.0))) : "Day"))
                .ForMember(d => d.subCategoryname, o => o.MapFrom(s => s.subCategoryId == 0 ? "" : Convert.ToString(subCategory.Where(z => z.subCategoryId.Equals(s.subCategoryId)).FirstOrDefault().subCategoryName)))
                .ForMember(d => d.optionalCategoryName, o => o.MapFrom(s => s.optCategoryId == 0 ? "" : Convert.ToString(optionalCategory.Where(z => z.optCategoryId.Equals(s.optCategoryId)).FirstOrDefault().optCategoryName)))
                .ForMember(d => d.logoImg, o => o.MapFrom(s => s.vendorId == 0 ? "" : Convert.ToString(vendorImg.Where(z => z.vendorId.Equals(s.vendorId)).FirstOrDefault().logoImg)))
                .ForMember(d => d.expiryDate, o => o.MapFrom(s => s.expiryDate == null ? "" : String.Format("{0:dd/MM/yyyy h:mm:ss tt}", s.expiryDate))); 
            var userPromotionModel = Mapper.Map<List<PromotionCode>, List<PromotionCodeEntity>>(promotionCode);
            return userPromotionModel;
        }
        return null;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.