では、任意の不明な要素を許可する明示的なデータ コントラクトはサポートされていませんDataContractSerializer
。 XmlSerializer
を介してこれをサポートします[XmlAnyElementAttribute]
が、回答Using [XmlAnyElement]で述べたように、データ コントラクトには同一の機能はありません。
あなたのクラスは を実装できますIExtensibleDataObject
。これは、前方互換性のあるデータ コントラクトに似て[XmlAnyElement]
おり、それを対象としています。残念ながら、その場合、不明な要素は不透明に格納され、値にアクセスする明白な方法はありません。このようなオブジェクトから XML を抽出することは可能ですが (こちらを参照) 、ラッパー クラス内で を再シリアル化し、結果を解析する必要があるため、自明ではなく、現在のコードよりもパフォーマンスが向上する可能性は低いです。ExtensionDataObject
ExtensionDataObject
パフォーマンスに関する 1 つの注意事項 - を実行するXDocument.Parse(reader.ReadOuterXml())
と、リファレンス ソースは、XML を効果的に解析し、 を介して にストリーミングしXmlWriter
、StringWriter
結果の文字列をもう一度解析していることを示しています。XNode.ReadFrom()
これを行う代わりに、次のように受信リーダーを呼び出すことで、XML を 1 回だけ解析できます。
public class CustomObject : IXmlSerializable
{
private readonly Dictionary<String, String> attributes = new Dictionary<string, string>();
public IDictionary<string, string> Attributes { get { return attributes; } }
#region IXmlSerializable Members
System.Xml.Schema.XmlSchema IXmlSerializable.GetSchema()
{
return null;
}
void IXmlSerializable.ReadXml(XmlReader reader)
{
var element = XElement.ReadFrom(reader) as XElement;
if (element != null)
{
foreach (var item in element.Elements())
attributes.Add(item.Name.LocalName, (string)item);
}
}
void IXmlSerializable.WriteXml(XmlWriter writer)
{
// Do NOT write the wrapper element when writing.
foreach (var pair in attributes)
{
writer.WriteElementString(pair.Key, pair.Value);
}
}
#endregion
}
これは、現在のクラスよりもパフォーマンスが向上するはずです。たとえば、大規模な動的 XML による Web API のパフォーマンスの問題では、同様の最適化で報告された改善は 40% でした。
アップデート
可能な限り最高のパフォーマンスを実装するには、特注のコードを使用してIXmlSerializable
コンテンツを直接読み取る必要があります。たとえば、次の例では、要素の名前と値をディクショナリXmlReader
に読み込みます。attributes
void IXmlSerializable.ReadXml(XmlReader reader)
{
if (reader.IsEmptyElement)
{
reader.Read();
return;
}
reader.Read();
while (reader.NodeType != XmlNodeType.EndElement)
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
var key = reader.Name;
var value = reader.ReadElementContentAsString();
attributes.Add(key, value);
break;
default:
// Comment, for instance.
reader.Read();
break;
}
}
// Consume the EndElement
reader.Read();
}
IXmlSerializable を実装する適切な方法を参照してください。要素階層を手動で正しく読み取るための一般的なガイドラインについては、