数据协定序列化程序 - 如何省略集合的外部元素

时间:2011-12-21 14:05:04

标签: c# xml-serialization datacontractserializer

如何使用数据合同序列化程序序列化没有外部元素的列表?我正在使用.Net 3.5。我有一个包含列表的类,除其他外,我希望序列化,而外部元素不符合相关的XSD:

[DataContract(Name="MyClass")]
public class MyClass
{
...
[DataMember(Name="Parameters")]
public List<Parameter> Parameters;
...
}

[DataContract(Name="Parameter")]
public struct Parameter
{
    [DataMember(Name="ValueName")]string ValueName;
    [DataMember(Name="Value")]int Value;
    public Parameter(string ValueName, int Value)
    {
        this.ValueName = ValueName;
        this.Value = Value;            
    }
}

以上序列化为(假设列表中只有一个参数):

<MyClass>
    <Parameters>
       <Parameter>
           <ValueName></ValueName>
           <Value></Value>
       </Parameter>
    </Parameters>
</MyClass>

我想将其序列化如下:

<MyClass> 
       <Parameter>
           <ValueName></ValueName>
           <Value></Value>
       </Parameter>
</MyClass>

使用XmlSerializer我可以通过将[XmlElement]应用于列表来完成此操作:

[XmlElement ("Parameter")]
public List<Parameter> Parameters;

但是我不想使用XmlSerializer,因为我的类有一些非序列化友好的属性,我希望处理那些使用[OnSerializing]属性系列的属性。

感谢。

3 个答案:

答案 0 :(得分:4)

DataContract序列化程序不允许对结果XML进行这种程度的控制,您必须使用XmlSerializer来实现此目的。

答案 1 :(得分:2)

使用收集数据合同:

    [CollectionDataContract(Name = "MyClass", ItemName = "Parameter")]
    public class ParameterList : List<Parameter>
    {

    }

以下是实际代码:

public class TestSerialize
{
    [DataContract(Name = "Parameter")]
    public struct Parameter
    {
        [DataMember(Name = "ValueName")] string ValueName;
        [DataMember(Name = "Value")] int Value;
        public Parameter(string ValueName, int Value)
        {
            this.ValueName = ValueName;
            this.Value = Value;
        }
    }

    [CollectionDataContract(Name = "MyClass", ItemName = "Parameter")]
    public class ParameterList : List<Parameter>
    {

    }


    public string Serialize(ParameterList plist)
    {
        var serializer = new DataContractSerializer(plist.GetType());
        var output = new StringBuilder();
        var xmlWriter = XmlWriter.Create(output);

        serializer.WriteObject(xmlWriter, plist);
        xmlWriter.Close();

        return output.ToString();
    }


    public void Serialize_produces_2Levels_of_xml()
    {
        ParameterList p = new ParameterList
        {
            new Parameter("First", 1),
            new Parameter("Second", 2),
        };

        var xml = Serialize(p);
    }
}

如果你运行它,你将获得以下XML:

<?xml version="1.0" encoding="utf-16"?>
<MyClass xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/Serialize.Test">
    <Parameter>
        <Value>1</Value>
        <ValueName>First</ValueName>
    </Parameter>
    <Parameter>
        <Value>2</Value>
        <ValueName>Second</ValueName>
    </Parameter>
</MyClass>

答案 2 :(得分:1)

下面的工作使用MessageContracts虽然是'hack' - 它将“MyClass”元素归属于List成员,并排除了“MyClass”的包装命名空间。

[ServiceContract(Namespace="")]
public interface IService1
{
    [OperationContract]
    MyClass GetParameters();
    // TODO: Add your service operations here
}

[DataContract(Namespace="")]
public class Parameter
{
    [DataMember]
    public string ValueName
    {
        get;
        set;
    }
    [DataMember]
    public int Value
    {
        get;
        set;
    }

    public Parameter(string ValueName, int Value) 
    { 
        this.ValueName = ValueName; 
        this.Value = Value; 
    } 
}

[MessageContract(IsWrapped = false, WrapperNamespace="")]
public class MyClass
{
    [MessageBodyMember(Name = "MyClass", Namespace = "")]
    public List<Parameter> Parameters
    {
        get;
        set;
    }
}
相关问题