private ExtensionObject ReadExtensionObject()
{
ExtensionObject extension = new ExtensionObject();
// read type id.
NodeId typeId = ReadNodeId(null);
// convert to absolute node id.
extension.TypeId = NodeId.ToExpandedNodeId(typeId, m_context.NamespaceUris);
if (!NodeId.IsNull(typeId) && NodeId.IsNull(extension.TypeId))
{
Utils.Trace(
"Cannot de-serialized extension objects if the NamespaceUri is not in the NamespaceTable: Type = {0}",
typeId);
}
// read encoding.
ExtensionObjectEncoding encoding = (ExtensionObjectEncoding)Enum.ToObject(typeof(ExtensionObjectEncoding), m_reader.ReadByte());
// nothing more to do for empty bodies.
if (encoding == ExtensionObjectEncoding.None)
{
return extension;
}
// check for known type.
Type systemType = m_context.Factory.GetSystemType(extension.TypeId);
// check for XML bodies.
if (encoding == ExtensionObjectEncoding.Xml)
{
extension.Body = ReadXmlElement(null);
// attempt to decode a known type.
if (systemType != null)
{
XmlElement element = extension.Body as XmlElement;
XmlDecoder xmlDecoder = new XmlDecoder(element, this.Context);
try
{
xmlDecoder.PushNamespace(element.NamespaceURI);
IEncodeable body = xmlDecoder.ReadEncodeable(element.LocalName, systemType);
xmlDecoder.PopNamespace();
// update body.
extension.Body = body;
}
catch (Exception e)
{
Utils.Trace("Could not decode known type {0}. Error={1}, Value={2}", systemType.FullName, e.Message, element.OuterXml);
}
}
return extension;
}
// create instance of type.
IEncodeable encodeable = null;
if (systemType != null)
{
encodeable = Activator.CreateInstance(systemType) as IEncodeable;
}
// get the length.
int length = ReadInt32(null);
// process unknown type.
if (encodeable == null)
{
// figure out how long the object is.
if (length == -1)
{
throw new ServiceResultException(
StatusCodes.BadDecodingError,
Utils.Format("Cannot determine length of unknown extension object body with type '{0}'.", extension.TypeId));
}
// check the length.
if (m_context.MaxByteStringLength > 0 && m_context.MaxByteStringLength < length)
{
throw ServiceResultException.Create(
StatusCodes.BadEncodingLimitsExceeded,
"MaxByteStringLength {0} < {1}",
m_context.MaxByteStringLength,
length);
}
// read the bytes of the body.
extension.Body = m_reader.ReadBytes(length);
return extension;
}
// save the current position.
int start = Position;
// decode body.
encodeable.Decode(this);
// skip any unread data.
int unused = length - (Position - start);
if (unused > 0)
{
m_reader.ReadBytes(unused);
}
extension.Body = encodeable;
return extension;
}
#endregion