【问题标题】:Data Contract Serializer - How to omit the outer element of a collectionData Contract Serializer - 如何省略集合的外部元素
【发布时间】:2011-12-21 14:05:04
【问题描述】:

如何使用 Data Contract Serializer 序列化没有外部元素的列表?我正在使用.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;            
    }
}

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

<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] 系列属性的属性。

谢谢。

【问题讨论】:

标签: c# xml-serialization datacontractserializer


【解决方案1】:

DataContract 序列化程序不允许对生成的 XML 进行这种程度的控制,您必须改用 XmlSerializer 才能实现这一点。

【讨论】:

  • 好的,谢谢。每当我搜索某件事而找不到它时,通常是因为它无法完成,或者它太愚蠢了,没有人想过这样做。感谢您确认前者;-)
  • 如何使用 XmlSerializer 来控制结果?
  • @natenho 看到这个问题,OP 已经在问题的底部有一个解决方案。
  • DataContractSerializer 可以产生如下所示的输出。说不能是错误的
【解决方案2】:

虽然是“hack”,但以下使用 MessageContracts 工作 - 它将“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;
    }
}

【讨论】:

    【解决方案3】:

    使用收集数据合同:

        [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>
    

    【讨论】:

    • 我不知道为什么有人对此投了反对票(也许他们可以就原因发表评论。它对我有用,并记录在这里:msdn.microsoft.com/en-us/library/…
    • 我想它被否决了,因为它仍然会导致 外部元素重复 子元素。该问题专门要求一种摆脱外部元素的方法。
    • 问题没有要求摆脱外部元素(MyClass),它要求摆脱下面的元素(参数)......这正是这个属性的作用!
    • 对于外部元素,我说的是 元素(或问题示例中的 ),而 是内部元素。
    • @SimonDowdeswell 请注意,在您的代码中,您只是在序列化ParameterList 的一个实例。该问题有一个带有Parameters 属性的MyClass 类。如果MyClass 也有其他属性(这是 OP 明确指出的:“我有一个包含列表的类,除其他外”),您的解决方案将不起作用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-18
    • 2010-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-05
    • 1970-01-01
    相关资源
    最近更新 更多