2016-12-02 27 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多个对象做了很棒的工作。这是我们挣扎的唯一对象,我不想改变我们的通用代码库,仅仅为了这个单一的异常。

相关问题