1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System; 6 using System.Xml; 7 using System.Collections.Generic; 8 using System.Globalization; 9 10 namespace System.Runtime.Serialization 11 { 12 public sealed class ExtensionDataObject 13 { 14 private IList<ExtensionDataMember> _members; 15 16 #if USE_REFEMIT || uapaot ExtensionDataObject()17 public ExtensionDataObject() 18 #else 19 internal ExtensionDataObject() 20 #endif 21 { 22 } 23 24 #if USE_REFEMIT || uapaot 25 public IList<ExtensionDataMember> Members 26 #else 27 internal IList<ExtensionDataMember> Members 28 #endif 29 { 30 get { return _members; } 31 set { _members = value; } 32 } 33 } 34 35 #if USE_REFEMIT || uapaot 36 public class ExtensionDataMember 37 #else 38 internal class ExtensionDataMember 39 #endif 40 { 41 private string _name; 42 private string _ns; 43 private IDataNode _value; 44 private int _memberIndex; 45 public string Name 46 { 47 get { return _name; } 48 set { _name = value; } 49 } 50 51 public string Namespace 52 { 53 get { return _ns; } 54 set { _ns = value; } 55 } 56 57 public IDataNode Value 58 { 59 get { return _value; } 60 set { _value = value; } 61 } 62 63 public int MemberIndex 64 { 65 get { return _memberIndex; } 66 set { _memberIndex = value; } 67 } 68 } 69 70 #if USE_REFEMIT || uapaot 71 public interface IDataNode 72 #else 73 internal interface IDataNode 74 #endif 75 { 76 Type DataType { get; } 77 object Value { get; set; } // boxes for primitives 78 string DataContractName { get; set; } 79 string DataContractNamespace { get; set; } 80 string ClrTypeName { get; set; } 81 string ClrAssemblyName { get; set; } 82 string Id { get; set; } 83 bool PreservesReferences { get; } 84 85 // NOTE: consider moving below APIs to DataNode<T> if IDataNode API is made public GetData(ElementData element)86 void GetData(ElementData element); 87 bool IsFinalValue { get; set; } Clear()88 void Clear(); 89 } 90 91 internal class DataNode<T> : IDataNode 92 { 93 protected Type dataType; 94 private T _value; 95 private string _dataContractName; 96 private string _dataContractNamespace; 97 private string _clrTypeName; 98 private string _clrAssemblyName; 99 private string _id = Globals.NewObjectId; 100 private bool _isFinalValue; 101 DataNode()102 internal DataNode() 103 { 104 this.dataType = typeof(T); 105 _isFinalValue = true; 106 } 107 DataNode(T value)108 internal DataNode(T value) 109 : this() 110 { 111 _value = value; 112 } 113 114 public Type DataType 115 { 116 get { return dataType; } 117 } 118 119 public object Value 120 { 121 get { return _value; } 122 set { _value = (T)value; } 123 } 124 125 bool IDataNode.IsFinalValue 126 { 127 get { return _isFinalValue; } 128 set { _isFinalValue = value; } 129 } 130 GetValue()131 public T GetValue() 132 { 133 return _value; 134 } 135 136 #if NotUsed SetValue(T value)137 public void SetValue(T value) 138 { 139 this.value = value; 140 } 141 #endif 142 143 public string DataContractName 144 { 145 get { return _dataContractName; } 146 set { _dataContractName = value; } 147 } 148 149 public string DataContractNamespace 150 { 151 get { return _dataContractNamespace; } 152 set { _dataContractNamespace = value; } 153 } 154 155 public string ClrTypeName 156 { 157 get { return _clrTypeName; } 158 set { _clrTypeName = value; } 159 } 160 161 public string ClrAssemblyName 162 { 163 get { return _clrAssemblyName; } 164 set { _clrAssemblyName = value; } 165 } 166 167 public bool PreservesReferences 168 { 169 get { return (Id != Globals.NewObjectId); } 170 } 171 172 public string Id 173 { 174 get { return _id; } 175 set { _id = value; } 176 } 177 GetData(ElementData element)178 public virtual void GetData(ElementData element) 179 { 180 element.dataNode = this; 181 element.attributeCount = 0; 182 element.childElementIndex = 0; 183 184 if (DataContractName != null) 185 AddQualifiedNameAttribute(element, Globals.XsiPrefix, Globals.XsiTypeLocalName, Globals.SchemaInstanceNamespace, DataContractName, DataContractNamespace); 186 if (ClrTypeName != null) 187 element.AddAttribute(Globals.SerPrefix, Globals.SerializationNamespace, Globals.ClrTypeLocalName, ClrTypeName); 188 if (ClrAssemblyName != null) 189 element.AddAttribute(Globals.SerPrefix, Globals.SerializationNamespace, Globals.ClrAssemblyLocalName, ClrAssemblyName); 190 } 191 Clear()192 public virtual void Clear() 193 { 194 // dataContractName not cleared because it is used when re-serializing from unknown data 195 _clrTypeName = _clrAssemblyName = null; 196 } 197 AddQualifiedNameAttribute(ElementData element, string elementPrefix, string elementName, string elementNs, string valueName, string valueNs)198 internal void AddQualifiedNameAttribute(ElementData element, string elementPrefix, string elementName, string elementNs, string valueName, string valueNs) 199 { 200 string prefix = ExtensionDataReader.GetPrefix(valueNs); 201 element.AddAttribute(elementPrefix, elementNs, elementName, String.Format(CultureInfo.InvariantCulture, "{0}:{1}", prefix, valueName)); 202 203 bool prefixDeclaredOnElement = false; 204 if (element.attributes != null) 205 { 206 for (int i = 0; i < element.attributes.Length; i++) 207 { 208 AttributeData attribute = element.attributes[i]; 209 if (attribute != null && attribute.prefix == Globals.XmlnsPrefix && attribute.localName == prefix) 210 { 211 prefixDeclaredOnElement = true; 212 break; 213 } 214 } 215 } 216 if (!prefixDeclaredOnElement) 217 element.AddAttribute(Globals.XmlnsPrefix, Globals.XmlnsNamespace, prefix, valueNs); 218 } 219 } 220 221 internal class ClassDataNode : DataNode<object> 222 { 223 private IList<ExtensionDataMember> _members; 224 ClassDataNode()225 internal ClassDataNode() 226 { 227 dataType = Globals.TypeOfClassDataNode; 228 } 229 230 internal IList<ExtensionDataMember> Members 231 { 232 get { return _members; } 233 set { _members = value; } 234 } 235 Clear()236 public override void Clear() 237 { 238 base.Clear(); 239 _members = null; 240 } 241 } 242 243 internal class XmlDataNode : DataNode<object> 244 { 245 private IList<XmlAttribute> _xmlAttributes; 246 private IList<XmlNode> _xmlChildNodes; 247 private XmlDocument _ownerDocument; 248 XmlDataNode()249 internal XmlDataNode() 250 { 251 dataType = Globals.TypeOfXmlDataNode; 252 } 253 254 internal IList<XmlAttribute> XmlAttributes 255 { 256 get { return _xmlAttributes; } 257 set { _xmlAttributes = value; } 258 } 259 260 internal IList<XmlNode> XmlChildNodes 261 { 262 get { return _xmlChildNodes; } 263 set { _xmlChildNodes = value; } 264 } 265 266 internal XmlDocument OwnerDocument 267 { 268 get { return _ownerDocument; } 269 set { _ownerDocument = value; } 270 } 271 Clear()272 public override void Clear() 273 { 274 base.Clear(); 275 _xmlAttributes = null; 276 _xmlChildNodes = null; 277 _ownerDocument = null; 278 } 279 } 280 281 internal class CollectionDataNode : DataNode<Array> 282 { 283 private IList<IDataNode> _items; 284 private string _itemName; 285 private string _itemNamespace; 286 private int _size = -1; 287 CollectionDataNode()288 internal CollectionDataNode() 289 { 290 dataType = Globals.TypeOfCollectionDataNode; 291 } 292 293 internal IList<IDataNode> Items 294 { 295 get { return _items; } 296 set { _items = value; } 297 } 298 299 internal string ItemName 300 { 301 get { return _itemName; } 302 set { _itemName = value; } 303 } 304 305 internal string ItemNamespace 306 { 307 get { return _itemNamespace; } 308 set { _itemNamespace = value; } 309 } 310 311 internal int Size 312 { 313 get { return _size; } 314 set { _size = value; } 315 } 316 GetData(ElementData element)317 public override void GetData(ElementData element) 318 { 319 base.GetData(element); 320 321 element.AddAttribute(Globals.SerPrefix, Globals.SerializationNamespace, Globals.ArraySizeLocalName, Size.ToString(NumberFormatInfo.InvariantInfo)); 322 } 323 Clear()324 public override void Clear() 325 { 326 base.Clear(); 327 _items = null; 328 _size = -1; 329 } 330 } 331 332 internal class ISerializableDataNode : DataNode<object> 333 { 334 private string _factoryTypeName; 335 private string _factoryTypeNamespace; 336 private IList<ISerializableDataMember> _members; 337 ISerializableDataNode()338 internal ISerializableDataNode() 339 { 340 dataType = Globals.TypeOfISerializableDataNode; 341 } 342 343 internal string FactoryTypeName 344 { 345 get { return _factoryTypeName; } 346 set { _factoryTypeName = value; } 347 } 348 349 internal string FactoryTypeNamespace 350 { 351 get { return _factoryTypeNamespace; } 352 set { _factoryTypeNamespace = value; } 353 } 354 355 internal IList<ISerializableDataMember> Members 356 { 357 get { return _members; } 358 set { _members = value; } 359 } 360 GetData(ElementData element)361 public override void GetData(ElementData element) 362 { 363 base.GetData(element); 364 365 if (FactoryTypeName != null) 366 AddQualifiedNameAttribute(element, Globals.SerPrefix, Globals.ISerializableFactoryTypeLocalName, Globals.SerializationNamespace, FactoryTypeName, FactoryTypeNamespace); 367 } 368 Clear()369 public override void Clear() 370 { 371 base.Clear(); 372 _members = null; 373 _factoryTypeName = _factoryTypeNamespace = null; 374 } 375 } 376 377 internal class ISerializableDataMember 378 { 379 private string _name; 380 private IDataNode _value; 381 382 internal string Name 383 { 384 get { return _name; } 385 set { _name = value; } 386 } 387 388 internal IDataNode Value 389 { 390 get { return _value; } 391 set { _value = value; } 392 } 393 } 394 } 395