[英]Predefine XML namespaces for DataContractSerializer
I'm building a self hosted WCF service.我正在构建一个自托管的 WCF 服务。 I'm building a special data structure for a very flexible transport of data.我正在为非常灵活的数据传输构建一个特殊的数据结构。 So far I test if my structure is serializable using the DataContractSerializer.到目前为止,我使用 DataContractSerializer 测试我的结构是否可序列化。 That works fine and I'm happy about that, but there is something annoying me:这很好用,我很高兴,但有些事情让我很烦:
In my XML output are dozens redefined xmlns attributes eg:在我的 XML 输出中有许多重新定义的 xmlns 属性,例如:
xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays"
xmlns:b="http://www.w3.org/2001/XMLSchema"
This should be better defined once in the root element so that bytes could be simply optimized.这应该在根元素中更好地定义一次,以便可以简单地优化字节。 Is there a way to add custom namespace informations to the root element?有没有办法将自定义命名空间信息添加到根元素?
Here is a bigger example to demonstrate what I mean:这是一个更大的例子来证明我的意思:
<DataObject xmlns="http://schemas.datacontract.org/2004/07/Test"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Data xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<a:KeyValueOfstringanyType>
<a:Key>ID</a:Key>
<a:Value i:type="b:int" xmlns:b="http://www.w3.org/2001/XMLSchema">1</a:Value>
</a:KeyValueOfstringanyType>
<a:KeyValueOfstringanyType>
<a:Key>Value</a:Key>
<a:Value i:type="b:int" xmlns:b="http://www.w3.org/2001/XMLSchema">42</a:Value>
</a:KeyValueOfstringanyType>
</Data>
<Data xmlns:a="...">...</Data>
<Data xmlns:a="...">...</Data>
<Data xmlns:a="...">...</Data>
</DataObject>
What I want is something like this:我想要的是这样的:
<DataObject xmlns="http://schemas.datacontract.org/2004/07/Test"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays"
xmlns:b="http://www.w3.org/2001/XMLSchema">
<Data>
<a:KeyValueOfstringanyType>
<a:Key>ID</a:Key>
<a:Value i:type="b:int">1</a:Value>
</a:KeyValueOfstringanyType>
<a:KeyValueOfstringanyType>
<a:Key>Value</a:Key>
<a:Value i:type="b:int">42</a:Value>
</a:KeyValueOfstringanyType>
</Data>
<Data>...</Data>
<Data>...</Data>
<Data>...</Data>
</DataObject>
static void Main()
{
var o = new Foo {
Prop = new Dictionary<string,string> { {"foo","bar"} }
};
var ms = new MemoryStream();
var slz = new DataContractSerializer(typeof(Foo));
slz.WriteObject(ms, o,
new Dictionary<string,string>
{
{ "arr", "http://schemas.microsoft.com/2003/10/Serialization/Arrays" },
});
string data = Encoding.UTF8.GetString(ms.ToArray());
Console.WriteLine(data);
}
public static class Extensions
{
public static void WriteObject(
this DataContractSerializer serializer,
Stream stream, object data,
Dictionary<string,string> namespaces)
{
using (var writer = XmlWriter.Create(stream))
{
serializer.WriteStartObject(writer, data);
foreach (var pair in namespaces)
{
writer.WriteAttributeString("xmlns", pair.Key, null, pair.Value);
}
serializer.WriteObjectContent(writer, data);
serializer.WriteEndObject(writer);
}
}
}
[DataContract]
class Foo
{
[DataMember]
public Dictionary<string,string> Prop;
}
Output:输出:
<?xml version="1.0" encoding="utf-8"?>
<Foo xmlns:arr="http://schemas.microsoft.com/2003/10/Serialization/Arrays"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://schemas.datacontract.org/2004/07/">
<Prop>
<arr:KeyValueOfstringstring>
<arr:Key>foo</arr:Key>
<arr:Value>bar</arr:Value>
</arr:KeyValueOfstringstring>
</Prop>
</Foo>
I successfully used the solution described here: http://blogs.msdn.com/b/youssefm/archive/2009/07/24/optimizing-away-repeat-xml-namespace-declarations-with-datacontractserializer.aspx我成功地使用了此处描述的解决方案:http: //blogs.msdn.com/b/youssefm/archive/2009/07/24/optimizing-away-repeat-xml-namespace-declarations-with-datacontractserializer.aspx
You basically create a behavior which adds the namespaces to the root element for you.您基本上创建了一个行为,为您将名称空间添加到根元素。
From the article:从文章:
Just create a serializer that inherits from XmlObjectSerializer that uses a DataContractSerializer for all of its methods, except for the fact that it registers additional namespaces at the top level.只需创建一个继承自 XmlObjectSerializer 的序列化程序,它的所有方法都使用 DataContractSerializer,除了它在顶层注册额外的命名空间这一事实。 Then create a behavior that derives from
DataContractSerializerOperationBehavior
with aCreateSerializer
method that returns theXmlObjectSerializer
you just created and plug in the behavior.然后使用CreateSerializer
方法创建一个派生自DataContractSerializerOperationBehavior
的行为,该方法返回您刚刚创建的XmlObjectSerializer
并插入该行为。
In case you want to do it in Silverlight, you can also use the solution described here: http://blogs.msdn.com/b/carlosfigueira/archive/2011/05/24/wcf-extensibility-custom-serialization-in-silverlight.aspx如果您想在 Silverlight 中执行此操作,您还可以使用此处描述的解决方案:http: //blogs.msdn.com/b/carlosfigueira/archive/2011/05/24/wcf-extensibility-custom-serialization-in -silverlight.aspx
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.