1 // 2 // SyndicationElementExtension.cs 3 // 4 // Author: 5 // Atsushi Enomoto <atsushi@ximian.com> 6 // 7 // Copyright (C) 2007 Novell, Inc (http://www.novell.com) 8 // 9 // Permission is hereby granted, free of charge, to any person obtaining 10 // a copy of this software and associated documentation files (the 11 // "Software"), to deal in the Software without restriction, including 12 // without limitation the rights to use, copy, modify, merge, publish, 13 // distribute, sublicense, and/or sell copies of the Software, and to 14 // permit persons to whom the Software is furnished to do so, subject to 15 // the following conditions: 16 // 17 // The above copyright notice and this permission notice shall be 18 // included in all copies or substantial portions of the Software. 19 // 20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 // 28 using System; 29 using System.Collections.Generic; 30 using System.Collections.ObjectModel; 31 using System.IO; 32 using System.Runtime.Serialization; 33 using System.Text; 34 using System.Xml; 35 using System.Xml.Serialization; 36 37 namespace System.ServiceModel.Syndication 38 { 39 public class SyndicationElementExtension 40 { 41 ReadWriteHandler handler; 42 SyndicationElementExtension(object dataContractExtension)43 public SyndicationElementExtension (object dataContractExtension) 44 : this (dataContractExtension, (XmlObjectSerializer) null) 45 { 46 } 47 SyndicationElementExtension(object dataContractExtension, XmlObjectSerializer dataContractSerializer)48 public SyndicationElementExtension (object dataContractExtension, XmlObjectSerializer dataContractSerializer) 49 : this (null, null, dataContractExtension, dataContractSerializer) 50 { 51 } 52 SyndicationElementExtension(string outerName, string outerNamespace, object dataContractExtension)53 public SyndicationElementExtension (string outerName, string outerNamespace, object dataContractExtension) 54 : this (outerName, outerNamespace, dataContractExtension, null) 55 { 56 } 57 SyndicationElementExtension(string outerName, string outerNamespace, object dataContractExtension, XmlObjectSerializer dataContractSerializer)58 public SyndicationElementExtension (string outerName, string outerNamespace, object dataContractExtension, XmlObjectSerializer dataContractSerializer) 59 { 60 if (dataContractExtension == null) 61 throw new ArgumentNullException ("dataContractExtension"); 62 handler = new DataContractReadWriteHandler (outerName, outerNamespace, dataContractExtension, dataContractSerializer); 63 } 64 SyndicationElementExtension(object xmlSerializerExtension, XmlSerializer serializer)65 public SyndicationElementExtension (object xmlSerializerExtension, XmlSerializer serializer) 66 { 67 if (xmlSerializerExtension == null) 68 throw new ArgumentNullException ("xmlSerializerExtension"); 69 handler = new XmlSerializationReadWriteHandler (xmlSerializerExtension, serializer); 70 } 71 SyndicationElementExtension(XmlReader xmlReader)72 public SyndicationElementExtension (XmlReader xmlReader) 73 { 74 if (xmlReader == null) 75 throw new ArgumentNullException ("xmlReader"); 76 xmlReader.MoveToContent (); 77 if (xmlReader.NodeType != XmlNodeType.Element) 78 throw new XmlException ("Element node is expected on the argument xmlReader"); 79 80 handler = new XmlReaderReadWriteHandler (xmlReader); 81 } 82 83 public string OuterName { 84 get { return handler != null ? handler.Name : null; } 85 } 86 87 public string OuterNamespace { 88 get { return handler != null ? handler.Namespace : null; } 89 } 90 GetObject()91 public TExtension GetObject<TExtension> () 92 { 93 return GetObject<TExtension> (new DataContractSerializer (typeof (TExtension))); 94 } 95 GetObject(XmlObjectSerializer serializer)96 public TExtension GetObject<TExtension> (XmlObjectSerializer serializer) 97 { 98 if (serializer == null) 99 throw new ArgumentNullException ("serializer"); 100 return (TExtension) serializer.ReadObject (GetReader (), false); 101 } 102 GetObject(XmlSerializer serializer)103 public TExtension GetObject<TExtension> (XmlSerializer serializer) 104 { 105 if (serializer == null) 106 throw new ArgumentNullException ("serializer"); 107 return (TExtension) serializer.Deserialize (GetReader ()); 108 } 109 GetReader()110 public XmlReader GetReader () 111 { 112 var r = handler.GetReader (); 113 r.MoveToContent (); 114 return r; 115 } 116 WriteTo(XmlWriter writer)117 public void WriteTo (XmlWriter writer) 118 { 119 if (writer == null) 120 throw new ArgumentNullException ("writer"); 121 122 handler.WriteTo (writer); 123 } 124 125 abstract class ReadWriteHandler 126 { 127 public string Name { get; protected set; } 128 129 public string Namespace { get; protected set; } 130 GetReader()131 public virtual XmlReader GetReader () 132 { 133 StringWriter sw = new StringWriter (); 134 using (XmlWriter w = XmlWriter.Create (sw)) 135 WriteTo (w); 136 return XmlReader.Create (new StringReader (sw.ToString ())); 137 } 138 WriteTo(XmlWriter writer)139 public abstract void WriteTo (XmlWriter writer); 140 } 141 142 class DataContractReadWriteHandler : ReadWriteHandler 143 { 144 object extension; 145 XmlObjectSerializer serializer; 146 DataContractReadWriteHandler(string name, string ns, object extension, XmlObjectSerializer serializer)147 public DataContractReadWriteHandler (string name, string ns, object extension, XmlObjectSerializer serializer) 148 { 149 if (serializer == null) 150 serializer = new DataContractSerializer (extension.GetType ()); 151 // FIXME: this is a nasty workaround that mcs somehow fails to resolve InternalVisibleTo(System.ServiceModel) in System.Runtime.Serialization.dll and thus rejects the use of KnownTypeCollection unlike NET_2_0 case (where System.ServiceModel.Web.dll is referenced). 152 XmlQualifiedName qname = null; 153 if (name == null || ns == null) { 154 var ms = new MemoryStream (); 155 using (var xw = XmlWriter.Create (ms)) 156 serializer.WriteStartObject (xw, extension); 157 ms.Position = 0; 158 var xr = XmlReader.Create (ms); 159 xr.MoveToContent (); 160 qname = new XmlQualifiedName (xr.LocalName, xr.NamespaceURI); 161 } 162 this.Name = name ?? qname.Name; 163 this.Namespace = ns ?? qname.Namespace; 164 this.extension = extension; 165 this.serializer = serializer; 166 } 167 WriteTo(XmlWriter writer)168 public override void WriteTo (XmlWriter writer) 169 { 170 if (Name != null) { 171 writer.WriteStartElement (Name, Namespace); 172 serializer.WriteObjectContent (writer, extension); 173 writer.WriteFullEndElement (); 174 } 175 else 176 serializer.WriteObject (writer, extension); 177 } 178 } 179 180 class XmlSerializationReadWriteHandler : ReadWriteHandler 181 { 182 object extension; 183 XmlSerializer serializer; 184 XmlSerializationReadWriteHandler(object extension, XmlSerializer serializer)185 public XmlSerializationReadWriteHandler (object extension, XmlSerializer serializer) 186 { 187 this.extension = extension; 188 this.serializer = serializer; 189 190 if (serializer == null) 191 serializer = new XmlSerializer (extension.GetType ()); 192 } 193 WriteTo(XmlWriter writer)194 public override void WriteTo (XmlWriter writer) 195 { 196 serializer.Serialize (writer, extension); 197 } 198 } 199 200 class XmlReaderReadWriteHandler : ReadWriteHandler 201 { 202 string xml; 203 XmlReaderReadWriteHandler(XmlReader reader)204 public XmlReaderReadWriteHandler (XmlReader reader) 205 { 206 reader.MoveToContent (); 207 Name = reader.LocalName; 208 Namespace = reader.NamespaceURI; 209 xml = reader.ReadOuterXml (); 210 } 211 GetReader()212 public override XmlReader GetReader () 213 { 214 var r = XmlReader.Create (new StringReader (xml)); 215 r.MoveToContent (); 216 return r; 217 } 218 WriteTo(XmlWriter writer)219 public override void WriteTo (XmlWriter writer) 220 { 221 writer.WriteNode (GetReader (), false); 222 } 223 } 224 } 225 } 226