【问题标题】:Serialize and Deserialize an XmlDocument in WCF using DataContractSerializer使用 DataContractSerializer 在 WCF 中序列化和反序列化 XmlDocument
【发布时间】:2009-05-18 20:51:19
【问题描述】:

我有一个 WCF 服务,它接受一个字符串作为其操作合同之一的参数。但是,此字符串中包含 xml 内容。

我需要将其转换为标记为DataContract 但不暴露于外界的类。

我需要使用DataContractSerializer,因为类成员的[DataMember] 属性设置为不同的名称。例如:Phone 属性的 DataMember Name 设置为 "Telephone",因此当我使用普通序列化程序反序列化 xmldocument 时,当反序列化程序查找不存在的 Phone 元素时出现错误。

如何使用DataContractSerializer 反序列化XmlDocument?一个限制是我无法将 xmldocument 保存到文件中。

编辑:找到一篇关于使用DataContractSerializer here.进行序列化和反序列化的优秀文章

我的客户代码:

string xmldata = "<Customer> + 
                System.Environment.NewLine+ 
                "<Age>1</Age>"+
                System.Environment.NewLine+
                "<BirthDate>1900-01-01T01:01:01.0000000-05:00</BirthDate>" + 
                System.Environment.NewLine+
                "<FistName>John</FistName>"+
                System.Environment.NewLine +
                "<LastName>Doe</LastName>" +
                System.Environment.NewLine +
                "</Customer>";

doc.LoadXml(xmldata); 
Service1Client a = new Service1Client();
a.GetData(doc.OuterXml.ToString());

我的服务代码:

public string GetData(string per)
{
    string xmldata = per;
    XmlDocument xmlDoc = new XmlDocument();
    xmlDoc.LoadXml(xmldata);
    XmlDemo.Person a = Person.Create();

    DataContractSerializer ser = new DataContractSerializer(a.GetType());
    StringWriter stringWriter = new StringWriter();
    XmlTextWriter xmlWriter = new XmlTextWriter(stringWriter);
    xmlDoc.WriteTo(xmlWriter);

    MemoryStream stream = new MemoryStream(Encoding.ASCII.GetBytes(stringWriter.ToString()));
    stream.Position = 0;
    XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(stream, new XmlDictionaryReaderQuotas());
    Person myContact = (Person)ser.ReadObject(reader, true);

    return string.Empty; 

}

我的数据合约:

[Serializable]
[DataContract(Name = "Customer")]
public class Person
{
    private Person() {}
    [DataMember(Name = "FistName")]
    public string FName { get; set; }
    [DataMember(Name = "LastName")]
    public string LName { get; set; }
    [DataMember(Name = "Age")]
    public int Age { get; set; }
    [DataMember(Name = "BirthDate")]
    public DateTime DOB { get; set; }

    public static Person Create()
    {
        return new Person();
    }
}

我在 Person myContact = (Person)ser.ReadObject(reader, true); 处收到此错误;

第 1 行位置 11 出错。从命名空间“http://schemas.datacontract.org/2004/07/XmlDemo”中期待元素“客户”。遇到名称为“客户”、命名空间“”的“元素”。

【问题讨论】:

  • 能否请您重新表述问题并更具体一点。我不明白你想要什么

标签: .net xml wcf


【解决方案1】:

直接从字符串反序列化

MemoryStream stream = new MemoryStream(Encoding.ASCII.GetBytes("<myXml />"));
stream.Position = 0;
XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(stream, new XmlDictionaryReaderQuotas());
MyContact myContact = (MyContact)ser.ReadObject(reader, true);

从 XmlDocument 反序列化

StringWriter stringWriter = new StringWriter();
XmlTextWriter xmlWriter = new XmlTextWriter(stringWriter);
xmlDoc.WriteTo(xmlWriter);

MemoryStream stream = new MemoryStream(Encoding.ASCII.GetBytes(stringWriter.ToString()));
stream.Position = 0;
XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(stream, new XmlDictionaryReaderQuotas());
MyContact myContact = (MyContact)ser.ReadObject(reader, true);

【讨论】:

  • 我尝试了你的方法,我已经列出了我的完整代码以及当我尝试使用你的代码时收到的错误消息。
  • 显然,您在 WCF 服务的某处声明了 schemas.datacontract.org/2004/07/XmlDemo 命名空间,在这种情况下,您需要注意反序列化程序的命名空间。
  • 以及如何使用相同的方法进行序列化??
【解决方案2】:

这是您的服务吗?如果是这样,那么不要在 string 参数中发送或接收 XML,因为它们不是同一个东西。

此外,虽然您还没有向世界公开您想要反序列化此 XML 的 DataContract,但您几乎已经通过公开 XML 实现了这一点。基本上是一样的效果。因此,您应该创建一个没有与之关联的行为的 DataContract 类,然后在您的 ServiceContract 中公开它。如果您需要在内部将其用作具有行为的类中的数据,则将数据复制到您永远不会公开的内部类的新实例中。


我仍然建议您停止这种愚蠢的做法,将 XML 复制到字符串中或从字符串中复制出来。不过,根据您发布的代码和异常:

为什么要这样做

XmlDemo.Person a = Person.Create();

然后在反序列化时将其清除?

XmlDemo.Person a;

足够了。然后使用 typeof(XmlDemo.Person) 代替 a.GetType()。

另外,您发布的 Person 类是否与“XmlDemo.Person”类完全相同?我很想知道那个命名空间是从哪里来的。要消除我的不确定性,请尝试将 [DataContract] 属性更改为 Namespace=String.Empty(或者 Namespace=null)。

最后,您是否听说过开发人员没有在实现 IDisposable 的类实例上调用 Dispose?

【讨论】:

  • 我发布的代码是我试图做的不同事情的混搭。工厂方法不属于那里。我想我应该在发布之前清理代码:) 我同意不将 xml 作为字符串传递,但是这种设计是由应用程序的“架构师”传下来的......
  • 谢谢你,John,你对命名空间的看法是对的,不幸的是 SO 不允许我将多个响应标记为答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-08-31
  • 2013-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-27
  • 2013-02-22
相关资源
最近更新 更多