| File: System\Runtime\Serialization\ExtensionDataObject.cs | Web Access |
| Project: src\runtime\src\libraries\System.Private.DataContractSerialization\src\System.Private.DataContractSerialization.csproj (System.Private.DataContractSerialization) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections.Generic; using System.Globalization; using System.Xml; namespace System.Runtime.Serialization { public sealed class ExtensionDataObject { private IList<ExtensionDataMember>? _members; internal ExtensionDataObject() { } internal IList<ExtensionDataMember>? Members { get { return _members; } set { _members = value; } } } internal sealed class ExtensionDataMember { private IDataNode? _value; private int _memberIndex; public ExtensionDataMember(string name, string ns) { Name = name; Namespace = ns; } public string Name { get; } public string Namespace { get; } public IDataNode? Value { get { return _value; } set { _value = value; } } public int MemberIndex { get { return _memberIndex; } set { _memberIndex = value; } } } internal interface IDataNode { Type DataType { get; } object? Value { get; set; } // boxes for primitives string? DataContractName { get; set; } string? DataContractNamespace { get; set; } string? ClrTypeName { get; set; } string? ClrAssemblyName { get; set; } string Id { get; set; } bool PreservesReferences { get; } // NOTE: consider moving below APIs to DataNode<T> if IDataNode API is made public void GetData(ElementData element); bool IsFinalValue { get; set; } void Clear(); } internal class DataNode<T> : IDataNode { protected Type dataType; private T _value = default!; private string? _dataContractName; private string? _dataContractNamespace; private string? _clrTypeName; private string? _clrAssemblyName; private string _id = Globals.NewObjectId; private bool _isFinalValue; internal DataNode() { this.dataType = typeof(T); _isFinalValue = true; } internal DataNode(T value) : this() { _value = value; } public Type DataType { get { return dataType; } } public object? Value { get { return _value; } set { _value = (T)value!; } } bool IDataNode.IsFinalValue { get { return _isFinalValue; } set { _isFinalValue = value; } } public T GetValue() { return _value; } public string? DataContractName { get { return _dataContractName; } set { _dataContractName = value; } } public string? DataContractNamespace { get { return _dataContractNamespace; } set { _dataContractNamespace = value; } } public string? ClrTypeName { get { return _clrTypeName; } set { _clrTypeName = value; } } public string? ClrAssemblyName { get { return _clrAssemblyName; } set { _clrAssemblyName = value; } } public bool PreservesReferences { get { return (Id != Globals.NewObjectId); } } public string Id { get { return _id; } set { _id = value; } } public virtual void GetData(ElementData element) { element.dataNode = this; element.attributeCount = 0; element.childElementIndex = 0; if (DataContractName != null) AddQualifiedNameAttribute(element, Globals.XsiPrefix, Globals.XsiTypeLocalName, Globals.SchemaInstanceNamespace, DataContractName, DataContractNamespace); if (ClrTypeName != null) element.AddAttribute(Globals.SerPrefix, Globals.SerializationNamespace, Globals.ClrTypeLocalName, ClrTypeName); if (ClrAssemblyName != null) element.AddAttribute(Globals.SerPrefix, Globals.SerializationNamespace, Globals.ClrAssemblyLocalName, ClrAssemblyName); } public virtual void Clear() { // dataContractName not cleared because it is used when re-serializing from unknown data _clrTypeName = _clrAssemblyName = null; } internal static void AddQualifiedNameAttribute(ElementData element, string elementPrefix, string elementName, string elementNs, string valueName, string? valueNs) { string prefix = ExtensionDataReader.GetPrefix(valueNs); element.AddAttribute(elementPrefix, elementNs, elementName, prefix + ":" + valueName); bool prefixDeclaredOnElement = false; if (element.attributes != null) { for (int i = 0; i < element.attributes.Length; i++) { AttributeData attribute = element.attributes[i]; if (attribute != null && attribute.prefix == Globals.XmlnsPrefix && attribute.localName == prefix) { prefixDeclaredOnElement = true; break; } } } if (!prefixDeclaredOnElement) element.AddAttribute(Globals.XmlnsPrefix, Globals.XmlnsNamespace, prefix, valueNs); } } internal sealed class ClassDataNode : DataNode<object> { private IList<ExtensionDataMember>? _members; internal ClassDataNode() { dataType = Globals.TypeOfClassDataNode; } internal IList<ExtensionDataMember>? Members { get { return _members; } set { _members = value; } } public override void Clear() { base.Clear(); _members = null; } } internal sealed class XmlDataNode : DataNode<object> { private IList<XmlAttribute>? _xmlAttributes; private IList<XmlNode>? _xmlChildNodes; private XmlDocument? _ownerDocument; internal XmlDataNode() { dataType = Globals.TypeOfXmlDataNode; } internal IList<XmlAttribute>? XmlAttributes { get { return _xmlAttributes; } set { _xmlAttributes = value; } } internal IList<XmlNode>? XmlChildNodes { get { return _xmlChildNodes; } set { _xmlChildNodes = value; } } internal XmlDocument? OwnerDocument { get { return _ownerDocument; } set { _ownerDocument = value; } } public override void Clear() { base.Clear(); _xmlAttributes = null; _xmlChildNodes = null; _ownerDocument = null; } } internal sealed class CollectionDataNode : DataNode<Array> { private IList<IDataNode?>? _items; private string? _itemName; private string? _itemNamespace; private int _size = -1; internal CollectionDataNode() { dataType = Globals.TypeOfCollectionDataNode; } internal IList<IDataNode?>? Items { get { return _items; } set { _items = value; } } internal string? ItemName { get { return _itemName; } set { _itemName = value; } } internal string? ItemNamespace { get { return _itemNamespace; } set { _itemNamespace = value; } } internal int Size { get { return _size; } set { _size = value; } } public override void GetData(ElementData element) { base.GetData(element); element.AddAttribute(Globals.SerPrefix, Globals.SerializationNamespace, Globals.ArraySizeLocalName, Size.ToString(NumberFormatInfo.InvariantInfo)); } public override void Clear() { base.Clear(); _items = null; _size = -1; } } internal sealed class ISerializableDataNode : DataNode<object> { private string? _factoryTypeName; private string? _factoryTypeNamespace; private IList<ISerializableDataMember>? _members; internal ISerializableDataNode() { dataType = Globals.TypeOfISerializableDataNode; } internal string? FactoryTypeName { get { return _factoryTypeName; } set { _factoryTypeName = value; } } internal string? FactoryTypeNamespace { get { return _factoryTypeNamespace; } set { _factoryTypeNamespace = value; } } internal IList<ISerializableDataMember>? Members { get { return _members; } set { _members = value; } } public override void GetData(ElementData element) { base.GetData(element); if (FactoryTypeName != null) AddQualifiedNameAttribute(element, Globals.SerPrefix, Globals.ISerializableFactoryTypeLocalName, Globals.SerializationNamespace, FactoryTypeName, FactoryTypeNamespace); } public override void Clear() { base.Clear(); _members = null; _factoryTypeName = _factoryTypeNamespace = null; } } internal sealed class ISerializableDataMember { private IDataNode? _value; public ISerializableDataMember(string name) { Name = name; } internal string Name { get; } internal IDataNode? Value { get { return _value; } set { _value = value; } } } }