2012-06-18 30 views
19

Tôi có một lớp dữ liệu được tuần tự hóa với DataContractSerializer. Lớp học sử dụng thuộc tính [DataContract] không có khai báo rõ ràng Namespace. Như vậy, không gian tên trong tệp xml kết quả được tạo ra dựa trên không gian tên của lớp.DataContractSerializer - thay đổi không gian tên và deserialize tập tin bị ràng buộc vào không gian tên cũ

Lớp cơ bản trông như thế này:

namespace XYZ 
{ 
    [DataContract] 
    public class Data 
    { 
     [DataMember(Order = 1)] 
     public string Prop1 { get; set; } 

     [DataMember(Order = 2)] 
     public int Prop2 { get; set; } 
    } 
} 

... và xml kết quả:

<?xml version="1.0" encoding="utf-8"?> 
<Data xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/XYZ"> 
    <Prop1>StringValue</Prop1> 
    <Prop2>11</Prop2> 
</Data> 

Bây giờ tôi muốn thay đổi không gian tên của lớp (trên thực tế loại bỏ nó) bằng cách thay đổi thuộc tính [DataContract] đến [DataContract(Namespace = "")]. Tuy nhiên, một khi tôi làm điều này bất kỳ tập tin trước đó được tuần tự hóa với không gian tên ban đầu không còn deserialize. Tôi nhận được ngoại lệ sau:

Error in line 1 position XXX. Expecting element 'Data' from namespace ''.. Encountered 'Element' with name 'Data', namespace 'http://schemas.datacontract.org/2004/07/XYZ'.

Điều này có ý nghĩa hoàn hảo. Tôi đã thay đổi không gian tên. Tôi ok với điều đó. Tuy nhiên, có vẻ như phải có một cách để nói cho các DataContractSerializer để đi trước và deserialize rằng dữ liệu ngay cả khi các không gian tên không phù hợp.

+0

Tại sao bạn muốn chỉ định chuỗi trống cho một không gian tên trong thuộc tính DataContract? Bạn đang đạt được điều gì bằng cách làm điều đó? –

+2

Tôi không bị ràng buộc với không gian tên CLR của lớp; và đó thực sự là vấn đề ở đây. Lớp này đang thay đổi không gian tên CLR của nó và tôi không muốn bị ràng buộc với chi tiết triển khai đó. Tôi có thể, tất nhiên, xác định một giá trị không gian tên xml mà tôi có thể giữ liên tục. Nhưng đối với việc thực hiện này, tôi không thấy lợi ích của việc đó so với việc loại bỏ không gian tên xml. Điều này đang được sử dụng cho serialization file đơn giản. – harlam357

Trả lời

15

Một cách có thể là bao bọc trình đọc được trình nối tiếp sử dụng trong trình đọc để ánh xạ không gian tên cũ tới không gian tên mới, như được hiển thị bên dưới. Rất nhiều mã, nhưng chủ yếu là tầm thường.

public class StackOverflow_11092274 
{ 
    const string XML = @"<?xml version=""1.0"" encoding=""utf-8""?> 
<Data xmlns:i=""http://www.w3.org/2001/XMLSchema-instance"" xmlns=""http://schemas.datacontract.org/2004/07/XYZ""> 
    <Prop1>StringValue</Prop1> 
    <Prop2>11</Prop2> 
</Data>"; 

    [DataContract(Name = "Data", Namespace = "")] 
    public class Data 
    { 
     [DataMember(Order = 1)] 
     public string Prop1 { get; set; } 

     [DataMember(Order = 2)] 
     public int Prop2 { get; set; } 
    } 

    public class MyReader : XmlReader 
    { 
     XmlReader inner; 
     public MyReader(XmlReader inner) 
     { 
      this.inner = inner; 
     } 

     public override int AttributeCount 
     { 
      get { return inner.AttributeCount; } 
     } 

     public override string BaseURI 
     { 
      get { return inner.BaseURI; } 
     } 

     public override void Close() 
     { 
      inner.Close(); 
     } 

     public override int Depth 
     { 
      get { return inner.Depth; } 
     } 

     public override bool EOF 
     { 
      get { return inner.EOF; } 
     } 

     public override string GetAttribute(int i) 
     { 
      return inner.GetAttribute(i); 
     } 

     public override string GetAttribute(string name, string namespaceURI) 
     { 
      return inner.GetAttribute(name, namespaceURI); 
     } 

     public override string GetAttribute(string name) 
     { 
      return inner.GetAttribute(name); 
     } 

     public override bool IsEmptyElement 
     { 
      get { return inner.IsEmptyElement; } 
     } 

     public override string LocalName 
     { 
      get { return inner.LocalName; } 
     } 

     public override string LookupNamespace(string prefix) 
     { 
      return inner.LookupNamespace(prefix); 
     } 

     public override bool MoveToAttribute(string name, string ns) 
     { 
      return inner.MoveToAttribute(name, ns); 
     } 

     public override bool MoveToAttribute(string name) 
     { 
      return inner.MoveToAttribute(name); 
     } 

     public override bool MoveToElement() 
     { 
      return inner.MoveToElement(); 
     } 

     public override bool MoveToFirstAttribute() 
     { 
      return inner.MoveToFirstAttribute(); 
     } 

     public override bool MoveToNextAttribute() 
     { 
      return inner.MoveToNextAttribute(); 
     } 

     public override XmlNameTable NameTable 
     { 
      get { return inner.NameTable; } 
     } 

     public override string NamespaceURI 
     { 
      get 
      { 
       if (inner.NamespaceURI == "http://schemas.datacontract.org/2004/07/XYZ") 
       { 
        return ""; 
       } 
       else 
       { 
        return inner.NamespaceURI; 
       } 
      } 
     } 

     public override XmlNodeType NodeType 
     { 
      get { return inner.NodeType; } 
     } 

     public override string Prefix 
     { 
      get { return inner.Prefix; } 
     } 

     public override bool Read() 
     { 
      return inner.Read(); 
     } 

     public override bool ReadAttributeValue() 
     { 
      return inner.ReadAttributeValue(); 
     } 

     public override ReadState ReadState 
     { 
      get { return inner.ReadState; } 
     } 

     public override void ResolveEntity() 
     { 
      inner.ResolveEntity(); 
     } 

     public override string Value 
     { 
      get { return inner.Value; } 
     } 
    } 

    public static void Test() 
    { 
     DataContractSerializer dcs = new DataContractSerializer(typeof(Data)); 
     MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(XML)); 
     try 
     { 
      XmlReader r = XmlReader.Create(ms); 
      XmlReader my = new MyReader(r); 
      Data d = (Data)dcs.ReadObject(my); 
      Console.WriteLine("Data[Prop1={0},Prop2={1}]", d.Prop1, d.Prop2); 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine(e); 
     } 
    } 
} 
+2

Điều này làm việc tuyệt vời! Tôi đã tấn công vấn đề ở cấp độ sai. Cám ơn rất nhiều! Tôi có một số loại dữ liệu phức tạp hơn có chứa các trường hợp 'Từ điển ' đã chứng minh một chút khó khăn hơn. Các thẻ cho mỗi KVP thay đổi, tôi giả định dựa trên sự thay đổi không gian tên, như vậy: '' đến ''. Tôi đã phải thực hiện một chuyển đổi thủ công trên các tập tin này, nhưng đó là ok. Những tập tin/loại này đại diện cho một số ít những gì cần phải được đọc. – harlam357

Các vấn đề liên quan