2017-09-14 69 views
1

我有以下表結構。這兩張桌子有很多共同的屬性超過20我剛剛列出兩個。還有我有10個表與此類似。這就是表格在數據庫中的方式。有超過10個具有類似屬性的混凝土表格,並且不以任何方式相互連接。我使用POCO生成器從我的數據庫生成類。Automapper:如何選擇重複映射?

public class A 
{ 
    public string name {get;set;} 
    public string address {get;set;} 
    public string AId {get;set;} 
    } 

public class B 
{ 
    public string name {get;set;} 
    public string address {get;set;} 
    public string BId {get;set;} 
    } 

我有以下的ViewModels:

public class BaseViewModel 
{ 
    public string Fullname {get;set;} 
    public string Fulladdress {get;set;} 
    } 

public class AviewModel : BaseViewModel 
{ 
    public string AId {get;set;} 
    } 

public class BViewModel : BaseViewModel 
{ 
    public string BId {get;set;} 
    } 

當我創建映射我不得不重複這一切,我已經創建的每個視圖模型。

config.CreateMap<A, AviewModel>() 
.ForMember(dest => Fulladdress, opt => opt.MapFrom(src =>.address)) 
.ForMember(dest => Fullname, opt => opt.MapFrom(src =>.name)).ReverseMap(); 


config.CreateMap<B, BviewModel>() 
.ForMember(dest => Fulladdress, opt => opt.MapFrom(src =>.address)) 
.ForMember(dest => Fullname, opt => opt.MapFrom(src =>.name)).ReverseMap(); 

是否有可能減少我可能需要做的重複映射?

+1

爲什麼不提取和使用基類爲您的實體,類似於你正在做你的視圖模型。 –

+0

@IvanStoev所以我使用POCO生成的類我不想手動更改類中的任何東西。所以這意味着每次有人更新.tt文件,我的結構已經消失了。 – hamadkh

+0

其實你是對的似乎是最好的解決方案 – hamadkh

回答

2

您可以將通用映射代碼移至輔助通用方法。您將限制TDestination類型爲從BaseViewModel派生的類,從而允許以ForMember方法訪問目標成員。而對於源映射你將使用MapFrom超負荷接受string屬性名稱:

public static class CommonMappings 
{ 
    public static IMappingExpression<TSource, TDestination> MapToBaseViewModel<TSource, TDestination>(this IMappingExpression<TSource, TDestination> map) 
     where TDestination : BaseViewModel 
    { 
     return map 
      .ForMember(dest => dest.Fulladdress, opt => opt.MapFrom("address")) 
      .ForMember(dest => dest.Fullname, opt => opt.MapFrom("name")); 
    } 
} 

然後你可以使用它像這樣:

config.CreateMap<A, AViewModel>() 
    .MapToBaseViewModel() 
    // ... specific mappings 
    .ReverseMap(); 

config.CreateMap<B, BViewModel>() 
    .MapToBaseViewModel() 
    // ... specific mappings 
    .ReverseMap(); 

更新:事實證明,在自動反向映射目前最新的AutoMapper 6.1.1適用於MapFrom的lambda超載,但不適用於string過載(在AutoMapper 5中根本不起作用)。所以,直到它被固定的,你可以使用下面的MapFrom(string)更換:

public static class AMExtensions 
{ 
    public static void From<TSource, TDestination, TMember>(this IMemberConfigurationExpression<TSource, TDestination, TMember> opt, string name) 
    { 
     var parameter = Expression.Parameter(typeof(TSource), "src"); 
     var body = Expression.PropertyOrField(parameter, name); 
     var selector = Expression.Lambda(body, parameter); 
     opt.MapFrom((dynamic)selector); 
    } 
} 

這意味着你需要在原來的解決方案與From取代MapFrom電話,因爲我們不能給的擴展方法相同的名稱因爲它比具體界面方法的優先級低。

與基準類方法相比,可能會花費太多精力。但有用的情況下,你無法控制實體類的設計。

+1

這也行得通,所以我在POCO生成的類之外創建了一個基類,並將其配置爲忽略常用字段並從我的基類繼承。我確實做得很好。我仍然會將這個commonMapping類用於其他小型重複映射。非常感謝 !! – hamadkh

+1

雖然很聰明,但這更像是一種破解:)我只會在沒有辦法創建源代碼基類/接口時才使用它。 –

+0

是的,我也只是測試它多一點,似乎reverseMap()不起作用呢?它獲取數據但不會發布給我? – hamadkh

0

您在模型上設置屬性的屬性。 這包含它在源對象上映射的屬性的名稱。

然後,您製作一個接受目標對象和源對象的通用方法,該方法在設置屬性的屬性和目標對象上的屬性(反之亦然)上找到customattribute,然後設置該值。

你甚至可以通過詢問是否它的一個類屬性來處理嵌套對象。

+0

因此,不是重複的流暢配置,而是建議重複數據註釋(自定義屬性)。有什麼不同 - 你仍然需要做很多重複的工作。 –

+0

呃不可以?你只需要爲一個類的屬性定義屬性一次。到源類型或反之亦然。比通用類爲您處理映射更少關注發送給映射器的類。不涉及重複性任務。 –

2

您需要源類的基類。您可以在基本源類和目標類之間創建一個映射。您可以在映射中爲派生類添加該映射。這將允許您重新使用配置。 The docs。對於簡單情況,您可以使用As而不是Include。