2013-05-10 219 views
1

我很难忽略继承自基类的类的属性。Automapper - 忽略基类上的属性

Mapper.CreateMap<FormViewModelBase, EntityBase>() 
.Include<FormViewModel, Entity>() 
.ForMember(x => x.Id, o => o.Ignore()); 

Mapper.CreateMap<FormViewModel, Entity>(); 

这里唯一需要注意的是基类的属性是String,派生类的属性是Int32。

无论如何,当我尝试将FormViewModel的实例映射到Entity时,实体类上的基于String的Id属性始终设置为来自FormViewModel的Int值,即使我已指定忽略它。

我在FormViewModel和Entity上使用不同类型的Id的原因是我在Web应用程序中使用RavenDB,并且可以通过字符串或int ID加载对象。在客户端的Int Id是首选的,因为标准的基于Raven字符串的ID在生成链接时播放不好。

任何人都可以告诉我这是什么问题吗?

+0

可能对我知道我正在映射到现有对象也有所帮助。 – JCoder23 2013-05-10 14:22:09

回答

1

所以你的基类看起来像这样?

public class FormViewModelBase 
{ 
    public string Id { get; set; } 
    // other stuff 
} 

和你的派生类看起来像这样吗?

public class FormViewModel : FormViewModelBase 
{ 
    public new int Id { get; set; } 
    // other stuff 
} 

我假设是这种情况。

如果是这种情况,那么派生ID将隐藏基本ID属性。

无论如何,你是否正在传递一个FormViewModel的实际实例并使它们产生Entity对象?

我看这样行:

Mapper.CreateMap<FormViewModel, Entity>(); 

这对我说:“让我一个新的Entity对象从FormViewModel对象我送你,做默认情况下,传统的事情做到这一点。”

所以,当你调用是这样的:

var anEntity = AutoMapper.Mapper.Map<FormViewModel, Entity>(aFormViewModel); 

它要使用地图,而不是一个基对象。因为它一个派生的FormViewModel

如果你不喜欢的东西:

Mapper.CreateMap<FormViewModel, Entity>() 
.ForMember(x => x.Id, o => o.Ignore()); 

处理您的派生类对象,它会映射它,我怀疑,映射,你会想,但它可能是有益的了解多了一些什么你正在努力。

+0

简单地说,即时尝试将从表单发布的模型映射到将保存在我的数据库中的实体。 FormViewModelBase有一个属性Id(Int32),FormViewModel继承自此。 FormViewModel类没有指定一个新的Id属性,它只是使用它的基类中的Id以及其他一些属性。我想从FormViewModel - > Entity进行映射时忽略Id。上面提供的映射代码不适用于我,我的实体上的属性总是被覆盖。 – JCoder23 2013-05-13 13:14:43

+0

好吧,所以FormViewModel没有一个Id,但实体有一个你想保留的。疑难杂症。在我的测试代码中,我在那里写了代码的最后一部分,在将FormViewModel映射到实体时执行了忽略ID,将保留实体的原始ID。 – itsmatt 2013-05-13 13:47:16

+0

好的,是的,这是我的工作,但根据Automapper文档,我应该能够忽略基类映射上的Id,所以我不必在每个子类映射上指定Ignore规则。 – JCoder23 2013-05-13 14:08:41

0

您需要指定映射子类而不是父母的映射详细信息(如忽略某些属性)。例如:

Mapper.CreateMap<ParentA, ParentB> 
     .Include<ChildA, ChildB>(); 

Mapper.CreateMap<ChildA, ChildB> 
     .ForMember(dest => dest.SomeProperty, opt => opt.Ignore()); 

你的代码不工作的原因是你在父映射中指定了Ignore()。

0

我知道这个问题已经有一年了,但是我还没有在SO中找到解决这类问题的解决方案。我有同样的问题,并经过一些挖掘,我发现唯一的事情是,这种行为没有很好的记录。映射基类可以工作,但忽略它们并不是出于某种原因。

我使用这个扩展的方法和它的工作对我来说

public static IMappingExpression<TSource, TDestination> 
     InheritMappingFromBaseType<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression) 
    { 
     var sourceType = typeof(TSource); 
     var desctinationType = typeof(TDestination); 
     var sourceParentType = sourceType.BaseType; 
     var destinationParentType = desctinationType.BaseType; 

     expression 
      .ForAllMembers(x => x.Condition(r => NotAlreadyMapped(sourceParentType, destinationParentType, r))); 

     return expression; 
    } 

    private static bool NotAlreadyMapped(Type sourceType, Type desitnationType, ResolutionContext r) 
    { 
     return !r.IsSourceValueNull && 
       Mapper.FindTypeMapFor(sourceType, desitnationType).GetPropertyMaps().Where(
        m => m.DestinationProperty.Name.Equals(r.MemberName)).Select(y => !y.IsMapped()).All(b => b); 
    } 

,这是它是如何使用的(请注意,您需要,但忽略基类映射声明)

CreateMap<DerivedClassSource, DerivedClassDestination>() 
      .InheritMappingFromBaseType() 

它所做的是映射任何未使用基类映射映射的属性。换句话说,它打破了默认的映射优先级。

我找到了源代码here,并修改了一点,因为原有的一些方法的代码在AutoMapper 2现在已经实现和3

0

提出这个与AutoMapper的问题后,即忽略的原因是不使用Include添加是因为没有办法忽略 - 映射仍然可以在基类中重写。

目前您可以实现此行为的唯一方法是使用[IgnoreMap]属性修饰目标属性,但这可能与您的其他配置不一致,因此您需要确定它是否值得!