object IStructuredReader.ReadInlineObject( out StandardReadStatus status ) { AssertCurrentReader(); XmlReader r = Xml; object o = null; string type = r.GetAttribute( "type" ); if( type == null ) { status = StandardReadStatus.ErrorTypeAttributeMissing; } else { status = StandardReadStatus.SimpleTypeData; switch( type ) { case "null": status = StandardReadStatus.NullData; r.Skip(); break; case "Enum": { status = StandardReadStatus.XmlSerializable; try { Type t = GetType( r.GetAttribute( "typeName" ) ); if( t == null ) { r.Skip(); } else { r.Read(); o = Enum.Parse( t, r.ReadContentAsString() ); } } finally { // On error, we can be on the <data key="..." type="Enum" typeName="..." > element or after its content: // by skipping, we either skip the content and the end element or the end element. r.Skip(); } break; } case "String": o = r.ReadElementString(); break; case "Int32": o = r.ReadElementContentAsInt(); break; case "Bool": o = XmlConvert.ToBoolean( r.ReadElementContentAsString() ); break; case "DateTimeOffset": o = XmlConvert.ToDateTimeOffset( r.ReadElementContentAsString() ); break; case "DateTime": o = XmlConvert.ToDateTime( r.ReadElementContentAsString(), XmlDateTimeSerializationMode.RoundtripKind ); break; case "TimeSpan": o = XmlConvert.ToTimeSpan( r.ReadElementContentAsString() ); break; case "Guid": o = XmlConvert.ToGuid( r.ReadElementContentAsString() ); break; case "Single": o = XmlConvert.ToSingle( r.ReadElementContentAsString() ); break; case "Double": o = XmlConvert.ToDouble( r.ReadElementContentAsString() ); break; case "Decimal": o = XmlConvert.ToDecimal( r.ReadElementContentAsString() ); break; case "Char": o = XmlConvert.ToChar( r.ReadElementContentAsString() ); break; case "UInt32": o = XmlConvert.ToUInt32( r.ReadElementContentAsString() ); break; case "Int16": o = XmlConvert.ToInt16( r.ReadElementContentAsString() ); break; case "UInt16": o = XmlConvert.ToUInt16( r.ReadElementContentAsString() ); break; case "Int64": o = XmlConvert.ToInt64( r.ReadElementContentAsString() ); break; case "UInt64": o = XmlConvert.ToUInt64( r.ReadElementContentAsString() ); break; case "Byte": o = XmlConvert.ToByte( r.ReadElementContentAsString() ); break; case "SByte": o = XmlConvert.ToSByte( r.ReadElementContentAsString() ); break; case "Structured": { status = StandardReadStatus.Structured; using( ISubStructuredReader rSub = OpenSubReader() ) { Type t = GetType( r.GetAttribute( "typeName" ) ); if( t != null ) o = ReadInlineObjectStructured( rSub, t, null ); } break; } case "XmlSerializable": { status = StandardReadStatus.XmlSerializable; using( Root.CreateJail() ) { Type t = GetType( r.GetAttribute( "typeName" ) ); if( t != null ) { o = Activator.CreateInstance( t ); IXmlSerializable xmlSer = (IXmlSerializable)o; xmlSer.ReadXml( Xml ); OnObjectRead( o, (IStructuredReader)this ); } } break; } case "Object": { status = StandardReadStatus.BinaryObject; try { int size = int.Parse( r.GetAttribute( "size" ) ); // Adds 8 bytes to the size. It allows to detect when the content is bigger than we expect. // ReadContentAsBinHex moves the reader to the next non-content element: this is either // the start element of extra data or the end of the current element. byte[] buffer = new byte[size + 8]; int readBytes = 0; // If an error occur while reading content, the reader.ReadState is Error // and this is definitive... r.Read(); readBytes = r.ReadContentAsBinHex( buffer, readBytes, buffer.Length ); if( readBytes != size ) throw new CKException( R.SizeDifferError, size, readBytes ); if( readBytes != -1 ) { BinaryFormatter f = new BinaryFormatter(); using( MemoryStream mem = new MemoryStream( buffer ) ) { try { o = f.Deserialize( mem ); } catch( Exception ex ) { throw new CKException( R.DeserializeError, ex ); } } OnObjectRead( o, (IStructuredReader)this ); } } catch( XmlException ex ) { throw new CKException( R.InvalidXml, ex ); } finally { // We are on the opening element OR on the closing tag. r.Skip(); } break; } default: { status = StandardReadStatus.ErrorUnknownTypeAttribute; break; } } } return o; }
object IStructuredReader.ReadInlineObject(out StandardReadStatus status) { AssertCurrentReader(); XmlReader r = Xml; object o = null; string type = r.GetAttribute("type"); if (type == null) { status = StandardReadStatus.ErrorTypeAttributeMissing; } else { status = StandardReadStatus.SimpleTypeData; switch (type) { case "null": status = StandardReadStatus.NullData; r.Skip(); break; case "Enum": { status = StandardReadStatus.XmlSerializable; try { Type t = GetType(r.GetAttribute("typeName")); if (t == null) { r.Skip(); } else { r.Read(); o = Enum.Parse(t, r.ReadContentAsString()); } } finally { // On error, we can be on the <data key="..." type="Enum" typeName="..." > element or after its content: // by skipping, we either skip the content and the end element or the end element. r.Skip(); } break; } case "String": o = r.ReadElementString(); break; case "Int32": o = r.ReadElementContentAsInt(); break; case "Bool": o = XmlConvert.ToBoolean(r.ReadElementContentAsString()); break; case "DateTimeOffset": o = XmlConvert.ToDateTimeOffset(r.ReadElementContentAsString()); break; case "DateTime": o = XmlConvert.ToDateTime(r.ReadElementContentAsString(), XmlDateTimeSerializationMode.RoundtripKind); break; case "TimeSpan": o = XmlConvert.ToTimeSpan(r.ReadElementContentAsString()); break; case "Guid": o = XmlConvert.ToGuid(r.ReadElementContentAsString()); break; case "Single": o = XmlConvert.ToSingle(r.ReadElementContentAsString()); break; case "Double": o = XmlConvert.ToDouble(r.ReadElementContentAsString()); break; case "Decimal": o = XmlConvert.ToDecimal(r.ReadElementContentAsString()); break; case "Char": o = XmlConvert.ToChar(r.ReadElementContentAsString()); break; case "UInt32": o = XmlConvert.ToUInt32(r.ReadElementContentAsString()); break; case "Int16": o = XmlConvert.ToInt16(r.ReadElementContentAsString()); break; case "UInt16": o = XmlConvert.ToUInt16(r.ReadElementContentAsString()); break; case "Int64": o = XmlConvert.ToInt64(r.ReadElementContentAsString()); break; case "UInt64": o = XmlConvert.ToUInt64(r.ReadElementContentAsString()); break; case "Byte": o = XmlConvert.ToByte(r.ReadElementContentAsString()); break; case "SByte": o = XmlConvert.ToSByte(r.ReadElementContentAsString()); break; case "Structured": { status = StandardReadStatus.Structured; using (ISubStructuredReader rSub = OpenSubReader()) { Type t = GetType(r.GetAttribute("typeName")); if (t != null) { o = ReadInlineObjectStructured(rSub, t, null); } } break; } case "XmlSerializable": { status = StandardReadStatus.XmlSerializable; using (Root.CreateJail()) { Type t = GetType(r.GetAttribute("typeName")); if (t != null) { o = Activator.CreateInstance(t); IXmlSerializable xmlSer = (IXmlSerializable)o; xmlSer.ReadXml(Xml); OnObjectRead(o, (IStructuredReader)this); } } break; } case "Object": { status = StandardReadStatus.BinaryObject; try { int size = int.Parse(r.GetAttribute("size")); // Adds 8 bytes to the size. It allows to detect when the content is bigger than we expect. // ReadContentAsBinHex moves the reader to the next non-content element: this is either // the start element of extra data or the end of the current element. byte[] buffer = new byte[size + 8]; int readBytes = 0; // If an error occur while reading content, the reader.ReadState is Error // and this is definitive... r.Read(); readBytes = r.ReadContentAsBinHex(buffer, readBytes, buffer.Length); if (readBytes != size) { throw new CKException(R.SizeDifferError, size, readBytes); } if (readBytes != -1) { BinaryFormatter f = new BinaryFormatter(); using (MemoryStream mem = new MemoryStream(buffer)) { try { o = f.Deserialize(mem); } catch (Exception ex) { throw new CKException(R.DeserializeError, ex); } } OnObjectRead(o, (IStructuredReader)this); } } catch (XmlException ex) { throw new CKException(R.InvalidXml, ex); } finally { // We are on the opening element OR on the closing tag. r.Skip(); } break; } default: { status = StandardReadStatus.ErrorUnknownTypeAttribute; break; } } } return(o); }