我有一个序列化与的DataContractSerializer
数据类。本类使用 [DataContract]
属性没有明确的命名空间
声明。这样,在所得到的xml文件命名空间是基于类的命名空间来产生的。
I have a data class that is serialized with the DataContractSerializer
. The class uses the [DataContract]
attribute with no explicit Namespace
declaration. As such, the namespace in the resulting xml file is generated based on the namespace of the class.
类基本上是这样的:
namespace XYZ
{
[DataContract]
public class Data
{
[DataMember(Order = 1)]
public string Prop1 { get; set; }
[DataMember(Order = 2)]
public int Prop2 { get; set; }
}
}
...和生成的XML:
...and the resulting 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]
属性 [DataContract(命名空间来改变类的命名空间(实际上是将其删除)= )]
。但是,一旦我这样做的任何文件previously序列与不再反序列化原来的命名空间。我收到以下异常:
Now I want to change the namespace of the class (actually remove it) by changing the [DataContract]
attribute to [DataContract(Namespace = "")]
. However, once I do this any file previously serialized with the original namespace with no longer deserialize. I receive the following exception:
在第1行的位置XXX错误。期望元素数据从命名空间......遇到元素名为'数据',命名空间http://schemas.datacontract.org/2004/07/XYZ'.
这是非常合情合理的。我改变了命名空间。我很确定这一点。然而,这似乎是必须有一个方法来告诉的DataContractSerializer
来继续和反序列化的数据,即使命名空间不匹配。
This makes perfect sense. I changed the namespace. I'm ok with that. However, it seems like there must be a way to tell the DataContractSerializer
to go ahead and deserialize that data even though the namespaces don't match.
一种可能的方式是包装,其中旧命名空间映射到新的一个,如下所示的读取器所使用的串行器的读取器。很多code,但大部分是微不足道的。
One possible way is to wrap the reader used by the serializer in a reader which maps the old namespace to the new one, as shown below. A lot of code, but mostly trivial.
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);
}
}
}