2013-05-10 97 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]屬性修飾目標屬性,但這可能與您的其他配置不一致,因此您需要確定它是否值得!