我目前正在处理的项目要求我将几个(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
。这些SHIPMENT节点与ROUTE_ACTIONS
将客户对象映射到我们自己的对象是非常可行的。我们只创建一个只有1 SHIPMENTS
个节点的新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;
}
}
}
答案 0 :(得分:0)
为了分享我对这个问题的了解,这是我到目前为止所提出的,它似乎正在发挥作用。我不会将其标记为确定的答案,因为有人可能会想出一个更好,更优雅的解决方案。
我所做的是最终使用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());
您可能会注意到我还必须将Destination模型更改为数组才能使用类型转换器。 它可能不是一个非常优雅的解决方案,但我想不出别的东西,仍然使用AutoMapper。
继续使用AutoMapper的主要原因是因为它对我们的其他50多个对象做得很好。这是我们努力的唯一对象,我不想改变我们的通用代码库,只是为了这个单一的异常。