2016-12-02 77 views
0

我目前正在處理的項目需要我將幾個(XML)對象映射到不同的對象。爲了讓我的生活更輕鬆,我決定使用AutoMapper來達到這個目的,並且它在促進所需功能方面做得很好。映射到不同的對象,取決於子集合

但是,有一個映射,我正在努力。

首先,讓我給你,我們是從客戶接收的XML:

<OURCOMPANY_ETA>   
    ... 
    <ROUTE_ACTIONS> 
     <TRIP>1294783</TRIP> 
     <SHIPMENT_NO>6483</SHIPMENT_NO> 
     <ACTION_TYPE>SomeOtherAction</ACTION_TYPE > 
     <ETA_DATE>2016-10-24</ETA_DATE> 
     <ETA_TIME>22:22</ETA_TIME> 
    </ROUTE_ACTIONS>  
    ... 
</OURCOMPANY_ETA>  

這應該會轉換爲一個對象看起來像這樣:

<?xml version="1.0" encoding="UTF-8"?>   
<OURCOMPANY_ETA>    
    .. 
    <SHIPMENTS>  
     <SHIPMENT> 
      <OURCOMPANYID>6483/1294783</OURCOMPANYID> 
      <ACTION_TYPE>SomeOtherAction</ACTION_TYPE> 
      <EDA>2016-10-24</EDA> 
      <ETA>22:22</ETA> 
     </SHIPMENT> 
    </SHIPMENTS> 
    ... 
</OURCOMPANY_ETA> 

你可能已經注意到了客戶有一個名爲ROUTE_ACTIONS的元素。這個元素不是您所期望的ROUTE_ACTION元素的集合,而只是包含一些數據的單個節點。 我們自己的XML包含一個SHIPMENTS節點,其子節點名爲SHIPMENT。這些裝運節點很好地匹配到ROUTE_ACTIONS

將客戶對象映射到我們自己的對象是非常有用的。我們只創建一個新節點SHIPMENTS,節點只有1個SHIPMENT,一切正常。 但是,當從我們自己的對象移回客戶的對象時會出現問題。客戶無法處理集合,因此我們必須爲自己的對象中的每個SHIPMENT節點創建一個新對象。

給出下面的XML

... 
<SHIPMENTS>  
    <SHIPMENT> 
     <OURCOMPANYID>6483/1294783</OURCOMPANYID> 
     <ACTION_TYPE>SomeOtherAction</ACTION_TYPE> 
     <EDA>2016-10-24</EDA> 
     <ETA>22:22</ETA> 
    </SHIPMENT> 
    <SHIPMENT> 
     <OURCOMPANYID>3123/47348236</OURCOMPANYID> 
     <ACTION_TYPE>SomeAction</ACTION_TYPE> 
     <EDA>2016-10-24</EDA> 
     <ETA>22:22</ETA> 
    </SHIPMENT> 
</SHIPMENTS> 
... 

我們將不得不創建2個對象,與此類似:

<OURCOMPANY_ETA>   
    ... 
    <ROUTE_ACTIONS> 
     <TRIP>1294783</TRIP> 
     <SHIPMENT_NO>6483</SHIPMENT_NO> 
     <ACTION_TYPE>SomeOtherAction</ACTION_TYPE > 
     <ETA_DATE>2016-10-24</ETA_DATE> 
     <ETA_TIME>22:22</ETA_TIME> 
    </ROUTE_ACTIONS>  
    ... 
</OURCOMPANY_ETA>  
<!--And another object--> 
<OURCOMPANY_ETA>   
    ... 
    <ROUTE_ACTIONS> 
     <TRIP>47348236</TRIP> 
     <SHIPMENT_NO>3123</SHIPMENT_NO> 
     <ACTION_TYPE>SomeAction</ACTION_TYPE > 
     <ETA_DATE>2016-10-24</ETA_DATE> 
     <ETA_TIME>22:22</ETA_TIME> 
    </ROUTE_ACTIONS> 
    ... 
</OURCOMPANY_ETA> 

如何處理這個使用AutoMapper任何想法?如果無法直接執行此操作,是否可以創建自己的邏輯並仍然使用AutoMapping來調用此邏輯,如使用IValueResolver

我已經使用Visual Studio將XML粘貼到對象來生成對象。爲了完整起見,他們可以在這篇文章的末尾找到。起初沒有添加它們,因爲它們很大。

我創建至今的映射如下:

CreateMap<Convertor.Customer.Model.Eta.OURCOMPANY_ETA, Convertor.Model.OURCOMPANY.Eta.OURCOMPANY_ETA>() 
     .ForMember(ed => ed.TIMESTAMP, opt => opt.MapFrom(es => es.DATETIME_CREATED)) 
     .ForMember(ed => ed.SHIPMENTS, opt => opt.MapFrom(es => es.ROUTE_ACTIONS)) 
     .ForMember(ed => ed.SUBCONTRACTOR_CODE, opt => opt.Ignore()) 
     .AfterMap((src, dest) => dest.VERSION = new decimal(2.0)); 
    CreateMap<Convertor.Model.OURCOMPANY.Eta.OURCOMPANY_ETA, Convertor.Customer.Model.Eta.OURCOMPANY_ETA>() 
     .ForMember(ed => ed.DATETIME_CREATED, opt => opt.MapFrom(es => es.TIMESTAMP)) 
     .ForMember(ed => ed.ROUTE_ACTIONS, opt => opt.MapFrom(es => es.SHIPMENTS)) 
     .AfterMap((src, dest) => dest.VERSION = new decimal(1.3)); 

CreateMap<Convertor.Customer.Model.Eta.OURCOMPANY_ETAROUTE_ACTIONS, Convertor.Model.OURCOMPANY.Eta.OURCOMPANY_ETASHIPMENT>() 
     .ForMember(ed => ed.OURCOMPANYID, opt => opt.ResolveUsing<EtaValueResolvers.GenerateOURCOMPANYId>()); 

    CreateMap<Convertor.Model.OURCOMPANY.Eta.OURCOMPANY_ETASHIPMENT, Convertor.Customer.Model.Eta.OURCOMPANY_ETAROUTE_ACTIONS>() 
     .ForMember(ed => ed.SHIPMENT_NO, opt => opt.ResolveUsing<EtaValueResolvers.ExtractShipmentOURCOMPANYId>()) 
     .ForMember(ed => ed.TRIP, opt => opt.ResolveUsing<EtaValueResolvers.ExtractTripOURCOMPANYId>()); 

公司它的目標是尋找這樣的:

/// <remarks/> 
[System.SerializableAttribute()] 
[System.ComponentModel.DesignerCategoryAttribute("code")] 
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] 
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)] 
public partial class OURCOMPANY_ETA 
{ 

    private System.DateTime tIMESTAMPField; 

    private string sUBCONTRACTOR_NAMEField; 

    private string sUBCONTRACTOR_CODEField; 

    private string OURCOMPANYCOMPANYField; 

    private decimal vERSIONField; 

    private OURCOMPANY_ETASHIPMENT[] sHIPMENTSField; 

    /// <remarks/> 
    public System.DateTime TIMESTAMP 
    { 
     get 
     { 
      return this.tIMESTAMPField; 
     } 
     set 
     { 
      this.tIMESTAMPField = value; 
     } 
    } 

    /// <remarks/> 
    public string SUBCONTRACTOR_NAME 
    { 
     get 
     { 
      return this.sUBCONTRACTOR_NAMEField; 
     } 
     set 
     { 
      this.sUBCONTRACTOR_NAMEField = value; 
     } 
    } 

    /// <remarks/> 
    public string SUBCONTRACTOR_CODE 
    { 
     get 
     { 
      return this.sUBCONTRACTOR_CODEField; 
     } 
     set 
     { 
      this.sUBCONTRACTOR_CODEField = value; 
     } 
    } 

    /// <remarks/> 
    public string OURCOMPANYCOMPANY 
    { 
     get 
     { 
      return this.OURCOMPANYCOMPANYField; 
     } 
     set 
     { 
      this.OURCOMPANYCOMPANYField = value; 
     } 
    } 

    /// <remarks/> 
    public decimal VERSION 
    { 
     get 
     { 
      return this.vERSIONField; 
     } 
     set 
     { 
      this.vERSIONField = value; 
     } 
    } 

    /// <remarks/> 
    [System.Xml.Serialization.XmlArrayItemAttribute("SHIPMENT", IsNullable = false)] 
    public OURCOMPANY_ETASHIPMENT[] SHIPMENTS 
    { 
     get 
     { 
      return this.sHIPMENTSField; 
     } 
     set 
     { 
      this.sHIPMENTSField = value; 
     } 
    } 
} 

/// <remarks/> 
[System.SerializableAttribute()] 
[System.ComponentModel.DesignerCategoryAttribute("code")] 
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] 
public partial class OURCOMPANY_ETASHIPMENT 
{ 

    private string OURCOMPANYIDField; 

    private string aCTION_TYPEField; 

    private System.DateTime eDAField; 

    private string eTAField; 

    /// <remarks/> 
    public string OURCOMPANYID 
    { 
     get 
     { 
      return this.OURCOMPANYIDField; 
     } 
     set 
     { 
      this.OURCOMPANYIDField = value; 
     } 
    } 

    /// <remarks/> 
    public string ACTION_TYPE 
    { 
     get 
     { 
      return this.aCTION_TYPEField; 
     } 
     set 
     { 
      this.aCTION_TYPEField = value; 
     } 
    } 

    /// <remarks/> 
    [System.Xml.Serialization.XmlElementAttribute(DataType = "date")] 
    public System.DateTime EDA 
    { 
     get 
     { 
      return this.eDAField; 
     } 
     set 
     { 
      this.eDAField = value; 
     } 
    } 

    /// <remarks/> 
    public string ETA 
    { 
     get 
     { 
      return this.eTAField; 
     } 
     set 
     { 
      this.eTAField = value; 
     } 
    } 
} 

客戶它的目標是尋找這樣的:

/// <remarks/> 
[System.SerializableAttribute()] 
[System.ComponentModel.DesignerCategoryAttribute("code")] 
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] 
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)] 
public partial class OURCOMPANY_ETA 
{ 

    private System.DateTime dATETIME_CREATEDField; 

    private string cHARTERCODEField; 

    private string OURCOMPANY_COMPANYField; 

    private decimal vERSIONField; 

    private OURCOMPANY_ETAROUTE_ACTIONS rOUTE_ACTIONSField; 

    /// <remarks/> 
    public System.DateTime DATETIME_CREATED 
    { 
     get 
     { 
      return this.dATETIME_CREATEDField; 
     } 
     set 
     { 
      this.dATETIME_CREATEDField = value; 
     } 
    } 

    /// <remarks/> 
    public string CHARTERCODE 
    { 
     get 
     { 
      return this.cHARTERCODEField; 
     } 
     set 
     { 
      this.cHARTERCODEField = value; 
     } 
    } 

    /// <remarks/> 
    public string OURCOMPANY_COMPANY 
    { 
     get 
     { 
      return this.OURCOMPANY_COMPANYField; 
     } 
     set 
     { 
      this.OURCOMPANY_COMPANYField = value; 
     } 
    } 

    /// <remarks/> 
    public decimal VERSION 
    { 
     get 
     { 
      return this.vERSIONField; 
     } 
     set 
     { 
      this.vERSIONField = value; 
     } 
    } 

    /// <remarks/> 
    public OURCOMPANY_ETAROUTE_ACTIONS ROUTE_ACTIONS 
    { 
     get 
     { 
      return this.rOUTE_ACTIONSField; 
     } 
     set 
     { 
      this.rOUTE_ACTIONSField = value; 
     } 
    } 
} 

/// <remarks/> 
[System.SerializableAttribute()] 
[System.ComponentModel.DesignerCategoryAttribute("code")] 
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] 
public partial class OURCOMPANY_ETAROUTE_ACTIONS 
{ 

    private string tRIPField; 

    private string sHIPMENT_NOField; 

    private string aCTION_TYPEField; 

    private System.DateTime eTA_DATEField; 

    private string eTA_TIMEField; 

    /// <remarks/> 
    public string TRIP 
    { 
     get 
     { 
      return this.tRIPField; 
     } 
     set 
     { 
      this.tRIPField = value; 
     } 
    } 

    /// <remarks/> 
    public string SHIPMENT_NO 
    { 
     get 
     { 
      return this.sHIPMENT_NOField; 
     } 
     set 
     { 
      this.sHIPMENT_NOField = value; 
     } 
    } 

    /// <remarks/> 
    public string ACTION_TYPE 
    { 
     get 
     { 
      return this.aCTION_TYPEField; 
     } 
     set 
     { 
      this.aCTION_TYPEField = value; 
     } 
    } 

    /// <remarks/> 
    [System.Xml.Serialization.XmlElementAttribute(DataType = "date")] 
    public System.DateTime ETA_DATE 
    { 
     get 
     { 
      return this.eTA_DATEField; 
     } 
     set 
     { 
      this.eTA_DATEField = value; 
     } 
    } 

    /// <remarks/> 
    public string ETA_TIME 
    { 
     get 
     { 
      return this.eTA_TIMEField; 
     } 
     set 
     { 
      this.eTA_TIMEField = value; 
     } 
    } 
} 
+1

您是否將XML轉換爲XML或對象爲對象?如果XML到XML,那麼XSLT比AutoMapper更好。如果對象是對象,請張貼您的類定義,而不是XML結構 – Rhumborl

+0

,因此您在結果xml中沒有'root'元素? – esiprogrammer

+0

請發佈一些C#代碼,查詢數據並調用AutoMapper。 –

回答

0

爲了分享我對這個問題的知識,下面是我想到的, r並且它似乎正在工作。我不會將它標記爲最終的答案,因爲有人可能會想出更好,更優雅的解決方案。

我所做的就是使用一個ITypeConverter,其中一個最終控制對象。但是,該解決方案與AutoMapper無關,除了仍使用該庫進行映射。

public class OurCompanyEtaToCustomerObjectsConvertor : ITypeConverter<Convertor.Model.OurCompany.Eta.OurCompany_ETA, Eta.OurCompany_ETA[]> 
{ 
    public Customer.Model.Eta.OurCompany_ETA[] Convert(Convertor.Model.OurCompany.Eta.OurCompany_ETA source, Customer.Model.Eta.OurCompany_ETA[] destination, ResolutionContext context) 
    { 
     destination = new Eta.OurCompany_ETA[0]; 
     if (source != null) 
     { 
      if (source.SHIPMENTS != null) 
      { 
       foreach (var OurCompanyEtashipment in source.SHIPMENTS) 
       { 
        var CustomerModel = new Customer.Model.Eta.OurCompany_ETA(); 
        //Other stuff.... 
        destination = destination.Concat(new[] {CustomerModel}).ToArray(); 
       } 
      }      
     } 
     return destination; 
    } 
} 

和地圖看起來是這樣的:

CreateMap<Convertor.Model.OurCompany.Eta.OurCompany_ETA, Convertor.Customer.Model.Eta.OurCompany_ETA[]>() 
      .ConvertUsing(new EtaValueResolvers.OurCompanyEtaToCustomerObjectsConvertor()); 

您可能注意到我也有目標的模型改變爲數組才能使用的類型轉換器。 這可能不是一個非常優雅的解決方案,但我想不到其他東西,仍然使用AutoMapper。

繼續使用AutoMapper的主要原因是因爲它爲我們的其他50多個對象做了很棒的工作。這是我們掙扎的唯一對象,我不想改變我們的通用代碼庫,僅僅爲了這個單一的異常。