2012-03-15 82 views
1

我正在使用c#和XmlSerialiser类从DTO对象创建xml。具有DTO对象中不同子节点的序列化节点

现在我不得不产生这样的XML文本:

<Order> 
    <OrderNo>123456</OrderNo> 
    <Positions> 
     <TextPosition> 
      <Text>This is Order No 123456</Text> 
     </TextPosition> 
     <ItemPosition> 
      <ItemId>14789</ItemId> 
      <ItemName>Product 1</ItemName> 
     </ItemPosition> 
     </TextPosition> 
     <ItemPosition> 
      <ItemId>456</ItemId> 
      <ItemName>Product 2</ItemName> 
     </ItemPosition> 
     <TextPosition> 
      <Text>Good bye</Text> 
     </TextPosition> 
     <SumPosition> 
      <Value>123.45 USD</Value> 
     </SumPosition> 
    </Positions> 
</Order> 

我使用属性来装饰我的班,一切工作正常。 我还无法解决的一件事。我需要用里面的不同标签TextPosition, ItemPosition, ValuePosition, ...生成一个标签Positions

如何在c#中实现此目的?

目前我Order类包含

[XmlElement("Positions")] 
public PositionList Positions { get; set; } 

PositionList是

public class PositionList 
{ 
    [XmlElement("Positions")] 
    public List<Object> Positions { get; set; } 
} 

一类为了避免出现InvalidOperationException我加

[XmlInclude(typeof(Textposition))] 
[XmlInclude(typeof(ItemPosition))] 
[XmlInclude(typeof(SumPosition))] 

我Order类。

然而,不是产生

<Positions> 
    <TextPosition>...</TextPosition> 
</Positions> 

串行产生:

<Position d4p1:type="TextPosition" xmlns:d4p1="http://www.w3.org/2001/XMLSchema-instance">...</Position> 

的事情是,在不需要反序列化我的自我但在一个非常提供一个XML文件严格格式为一个客户。有没有办法实现这个?

回答

2

有一个办法:

public class Order 
{ 
    public List<BasePosition> Positions { get; set; } 
    public Order() { Positions = new List<BasePosition>(); } 
} 

public class BasePosition 
{ 

} 

public class TextPosition : BasePosition 
{ 
    public string Text { get; set; } 
} 

public class ItemPosition : BasePosition 
{ 
    public int ItemId { get; set; } 
    public string ItemName { get; set; } 
} 

public class SumPosition : BasePosition 
{ 
    public string Value { get; set; } 
} 

例如,它序列化到一个XML文件:

Order o = new Order(); 
o.Positions.Add(new TextPosition() { Text = "This is Order No 123456" }); 
o.Positions.Add(new ItemPosition() { ItemId = 14789, ItemName = "Product 1" }); 
o.Positions.Add(new TextPosition()); 
o.Positions.Add(new ItemPosition() { ItemId = 456, ItemName = "Product 2" }); 
o.Positions.Add(new SumPosition() { Value = "123.45 USB" }); 
XmlAttributeOverrides specific_attributes = new XmlAttributeOverrides(); 
XmlAttributes attrs = new XmlAttributes(); 
attrs.XmlElements.Add(new XmlElementAttribute(typeof(TextPosition))); 
attrs.XmlElements.Add(new XmlElementAttribute(typeof(ItemPosition))); 
attrs.XmlElements.Add(new XmlElementAttribute(typeof(SumPosition))); 
specific_attributes.Add(typeof(Order), "Positions", attrs); 
XmlSerializer ser = new XmlSerializer(typeof(Order), specific_attributes); 

using(MemoryStream mem_stream = new MemoryStream()) 
{ 
    ser.Serialize(mem_stream, o); 
    using (BinaryWriter bw = new BinaryWriter(new FileStream("orders.xml", FileMode.Create))) 
    { 
     bw.Write(mem_stream.ToArray()); 
    } 
} 

结果:

<?xml version="1.0"?> 
<Order xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <TextPosition> 
    <Text>This is Order No 123456</Text> 
    </TextPosition> 
    <ItemPosition> 
    <ItemId>14789</ItemId> 
    <ItemName>Product 1</ItemName> 
    </ItemPosition> 
    <TextPosition /> 
    <ItemPosition> 
    <ItemId>456</ItemId> 
    <ItemName>Product 2</ItemName> 
    </ItemPosition> 
    <SumPosition> 
    <Value>123.45 USB</Value> 
    </SumPosition> 
</Order> 
+1

太棒了!我添加了一个辅助类PositionList,其中一个属性为'公共列表职位{get; set;}'以在订单和职位之间获得额外的''标签,但是,这确实实现了。非常感谢你。 – 2012-03-15 17:03:05

+0

没问题,很高兴我能帮忙,对不起,我错过了额外的标签:) – SwDevMan81 2012-03-15 17:34:49

1

当您以非常严格的格式需要XML时,使用序列化程序可能不是最佳选择。使用序列化程序时,为了方便起见,您放弃了控制权,现在您正在努力争取控制权。

考虑使用Linq to XML,即XDocument类。

var doc = 
    new XElement("Order", 
     new XElement ("OrderNo", 123456), 
     new XElement ("Positions", 
     myPositions.Select(p => new XElement("Position", ....))); 
+0

“你放弃控制方便,现在你正在努力争取控制权。“这是非常好的。 – 2012-03-15 16:04:50

+0

'你为了方便放弃了控制权,现在你正在努力控制这个控制权'我不同意这个控制权。使用Attributes和XmlSerializer的AOP方法非常强大,并且使用'XmlAttributeOverrides'我可以产生我需要的结果。由于DTO类生活在另一个dll,而不是序列化程序,所以我能够在未改变逻辑的情况下应用更新。无论如何,XDocument方法的+1,看起来很有前景(也许我考虑将它用于未来的其他任务)。 – 2012-03-15 17:37:59

相关问题