Пример #1
0
        /// <summary>
        /// Returns a list of references to the specified target.
        /// </summary>
        /// <param name="targetId">The target identifier.</param>
        /// <returns>A list of references to the specified target.</returns>
        public IList <IReference> FindReferencesToTarget(ExpandedNodeId targetId)
        {
            List <IReference> hits = new List <IReference>();

            // check for null.
            if (NodeId.IsNull(targetId))
            {
                return(hits);
            }

            // go throw list of references.
            for (LinkedListNode <KeyValuePair <IReference, T> > node = m_list.First; node != null; node = node.Next)
            {
                if (node.Value.Key.TargetId == targetId)
                {
                    hits.Add(node.Value.Key);
                }
            }

            return(hits);
        }
Пример #2
0
        /// <summary>
        /// Returns true if the reference type is required.
        /// </summary>
        public virtual bool IsRequired(NodeId referenceType, bool isInverse)
        {
            if (NodeId.IsNull(referenceType))
            {
                return(false);
            }

            // easiet to check inverse flag first.
            if (isInverse)
            {
                if (m_browseDirection == BrowseDirection.Forward)
                {
                    return(false);
                }
            }
            else
            {
                if (m_browseDirection == BrowseDirection.Inverse)
                {
                    return(false);
                }
            }

            // check for no filter or exact match.
            if (NodeId.IsNull(m_referenceType) || referenceType == m_referenceType)
            {
                return(true);
            }

            // check subtypes if possible.
            if (m_includeSubtypes && m_context != null)
            {
                if (m_context.TypeTable.IsTypeOf(referenceType, m_referenceType))
                {
                    return(true);
                }
            }

            return(false);
        }
Пример #3
0
        /// <summary>
        /// Removes a view from the table.
        /// </summary>
        /// <param name="viewId">The view identifier.</param>
        public void Remove(NodeId viewId)
        {
            if (NodeId.IsNull(viewId))
            {
                throw new ArgumentNullException("viewId");
            }

            lock (m_lock) {
                // find view.
                ViewNode view = null;

                if (!m_views.TryGetValue(viewId, out view))
                {
                    throw new ServiceResultException(
                              StatusCodes.BadViewIdUnknown,
                              Utils.Format("A reference type with the node id '{0}' does not exist.", viewId));
                }

                // remove view node.
                m_views.Remove(viewId);
            }
        }
Пример #4
0
        /// <summary>
        /// Validates a read value id parameter.
        /// </summary>
        public static ServiceResult Validate(HistoryReadValueId valueId)
        {
            // check for null structure.
            if (valueId == null)
            {
                return(StatusCodes.BadStructureMissing);
            }

            // null node ids are always invalid.
            if (NodeId.IsNull(valueId.NodeId))
            {
                return(StatusCodes.BadNodeIdInvalid);
            }

            // initialize as empty.
            valueId.ParsedIndexRange = NumericRange.Empty;

            // parse the index range if specified.
            if (!String.IsNullOrEmpty(valueId.IndexRange))
            {
                try
                {
                    valueId.ParsedIndexRange = NumericRange.Parse(valueId.IndexRange);
                }
                catch (Exception e)
                {
                    return(ServiceResult.Create(e, StatusCodes.BadIndexRangeInvalid, String.Empty));
                }
            }
            else
            {
                valueId.ParsedIndexRange = NumericRange.Empty;
            }

            // passed basic validation.
            return(null);
        }
Пример #5
0
        /// <summary>
        /// Updates the nodeset string tables and returns a NodeId that references those tables.
        /// </summary>
        /// <param name="nodeId">The node identifier.</param>
        /// <param name="targetNamespaceUris">The target namespace URIs.</param>
        /// <param name="sourceNamespaceUris">The source namespace URIs.</param>
        /// <returns>A NodeId that references those tables.</returns>
        private static NodeId Translate(
            NodeId nodeId,
            NamespaceTable targetNamespaceUris,
            NamespaceTable sourceNamespaceUris)
        {
            if (targetNamespaceUris == null)
            {
                throw new ArgumentNullException("targetNamespaceUris");
            }
            if (sourceNamespaceUris == null)
            {
                throw new ArgumentNullException("sourceNamespaceUris");
            }

            if (NodeId.IsNull(nodeId))
            {
                return(nodeId);
            }

            ushort namespaceIndex = 0;

            if (nodeId.NamespaceIndex > 0)
            {
                string uri = sourceNamespaceUris.GetString(nodeId.NamespaceIndex);

                int index = targetNamespaceUris.GetIndex(uri);

                if (index == -1)
                {
                    index = targetNamespaceUris.Append(uri);
                }

                namespaceIndex = (ushort)index;
            }

            return(new NodeId(nodeId.Identifier, namespaceIndex));
        }
Пример #6
0
        /// <summary>
        /// Exports a copt of the node to a node table.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="node">The node.</param>
        protected override void Export(ISystemContext context, Node node)
        {
            base.Export(context, node);

            if (!NodeId.IsNull(this.SuperTypeId))
            {
                node.ReferenceTable.Add(ReferenceTypeIds.HasSubtype, true, this.SuperTypeId);
            }

            switch (this.NodeClass)
            {
            case NodeClass.ObjectType:
            {
                ((ObjectTypeNode)node).IsAbstract = IsAbstract;
                break;
            }

            case NodeClass.VariableType:
            {
                ((VariableTypeNode)node).IsAbstract = IsAbstract;
                break;
            }

            case NodeClass.DataType:
            {
                ((DataTypeNode)node).IsAbstract = IsAbstract;
                break;
            }

            case NodeClass.ReferenceType:
            {
                ((ReferenceTypeNode)node).IsAbstract = IsAbstract;
                break;
            }
            }
        }
        /// <summary>
        /// Adds a node to the type table if it is a type and does not already exist. If it exists references are updated.
        /// </summary>
        /// <param name="node">The node.</param>
        public void Add(ILocalNode node)
        {
            // ignore null.
            if (node == null || NodeId.IsNull(node.NodeId))
            {
                return;
            }

            // ignore non-types.
            if ((node.NodeClass & (NodeClass.ObjectType | NodeClass.VariableType | NodeClass.ReferenceType | NodeClass.DataType)) == 0)
            {
                return;
            }

            NodeId localsuperTypeId = null;

            // find the supertype.
            ExpandedNodeId superTypeId = node.References.FindTarget(ReferenceTypeIds.HasSubtype, true, false, null, 0);

            if (superTypeId != null)
            {
                localsuperTypeId = ExpandedNodeId.ToNodeId(superTypeId, m_namespaceUris);

                if (localsuperTypeId == null)
                {
                    throw ServiceResultException.Create(StatusCodes.BadNodeIdInvalid, "A valid supertype identifier is required.");
                }
            }

            lock (m_lock)
            {
                // lookup the supertype.
                TypeInfo superTypeInfo = null;

                if (localsuperTypeId != null)
                {
                    if (!m_nodes.TryGetValue(localsuperTypeId, out superTypeInfo))
                    {
                        throw ServiceResultException.Create(StatusCodes.BadNodeIdInvalid, "A valid supertype identifier is required.");
                    }
                }

                // create the type info.
                TypeInfo typeInfo = null;

                if (!m_nodes.TryGetValue(node.NodeId, out typeInfo))
                {
                    typeInfo = new TypeInfo();
                    m_nodes.Add(node.NodeId, typeInfo);
                }

                // update the info.
                typeInfo.NodeId    = node.NodeId;
                typeInfo.SuperType = superTypeInfo;
                typeInfo.Deleted   = false;

                // add to supertype.
                if (superTypeInfo != null)
                {
                    superTypeInfo.AddSubType(typeInfo);
                }

                // remove the encodings.
                if (typeInfo.Encodings != null)
                {
                    foreach (NodeId encoding in typeInfo.Encodings)
                    {
                        m_encodings.Remove(encoding);
                    }
                }

                // any new encodings.
                IList <IReference> encodings = node.References.Find(ReferenceTypeIds.HasEncoding, false, false, null);

                if (encodings.Count > 0)
                {
                    typeInfo.Encodings = new NodeId[encodings.Count];

                    for (int ii = 0; ii < encodings.Count; ii++)
                    {
                        typeInfo.Encodings[ii] = ExpandedNodeId.ToNodeId(encodings[ii].TargetId, m_namespaceUris);
                        m_encodings[typeInfo.Encodings[ii]] = typeInfo;
                    }
                }

                // add reference type.
                if ((node.NodeClass & NodeClass.ReferenceType) != 0)
                {
                    if (!QualifiedName.IsNull(typeInfo.BrowseName))
                    {
                        m_referenceTypes.Remove(typeInfo.BrowseName);
                    }

                    typeInfo.BrowseName = node.BrowseName;

                    m_referenceTypes[node.BrowseName] = typeInfo;
                }
            }
        }
        /// <summary>
        /// Creates a new instance.
        /// </summary>
        /// <param name="context">The current context.</param>
        /// <param name="parent">The parent.</param>
        /// <param name="nodeClass">The node class.</param>
        /// <param name="browseName">The browse name.</param>
        /// <param name="referenceTypeId">The reference type between the parent and the node.</param>
        /// <param name="typeDefinitionId">The type definition.</param>
        /// <returns>Returns null if the type is not known.</returns>
        public virtual NodeState CreateInstance(
            ISystemContext context,
            NodeState parent,
            NodeClass nodeClass,
            QualifiedName browseName,
            NodeId referenceTypeId,
            NodeId typeDefinitionId)
        {
            NodeState child = null;

            if (m_types != null && !NodeId.IsNull(typeDefinitionId))
            {
                Type type = null;

                if (m_types.TryGetValue(typeDefinitionId, out type))
                {
                    return(Activator.CreateInstance(type, parent) as NodeState);
                }
            }

            switch (nodeClass)
            {
            case NodeClass.Variable:
            {
                if (context.TypeTable != null && context.TypeTable.IsTypeOf(referenceTypeId, ReferenceTypeIds.HasProperty))
                {
                    child = new PropertyState(parent);
                    break;
                }

                child = new BaseDataVariableState(parent);
                break;
            }

            case NodeClass.Object:
            {
                child = new BaseObjectState(parent);
                break;
            }

            case NodeClass.Method:
            {
                child = new MethodState(parent);
                break;
            }

            case NodeClass.ReferenceType:
            {
                child = new ReferenceTypeState();
                break;
            }

            case NodeClass.ObjectType:
            {
                child = new BaseObjectTypeState();
                break;
            }

            case NodeClass.VariableType:
            {
                child = new BaseDataVariableTypeState();
                break;
            }

            case NodeClass.DataType:
            {
                child = new DataTypeState();
                break;
            }

            case NodeClass.View:
            {
                child = new ViewState();
                break;
            }

            default:
            {
                child = null;
                break;
            }
            }

            return(child);
        }
Пример #9
0
        /// <summary>
        /// Parses a relative path formatted as a string.
        /// </summary>
        public static RelativePath Parse(string browsePath, ITypeTable typeTree)
        {
            if (typeTree == null)
            {
                throw new ArgumentNullException("typeTree");
            }

            // parse the string.
            RelativePathFormatter formatter = RelativePathFormatter.Parse(browsePath);

            // convert the browse names to node ids.
            RelativePath relativePath = new RelativePath();

            foreach (RelativePathFormatter.Element element in formatter.Elements)
            {
                RelativePathElement parsedElement = new RelativePathElement();

                parsedElement.ReferenceTypeId = null;
                parsedElement.IsInverse       = false;
                parsedElement.IncludeSubtypes = element.IncludeSubtypes;
                parsedElement.TargetName      = element.TargetName;

                switch (element.ElementType)
                {
                case RelativePathFormatter.ElementType.AnyHierarchical:
                {
                    parsedElement.ReferenceTypeId = ReferenceTypeIds.HierarchicalReferences;
                    break;
                }

                case RelativePathFormatter.ElementType.AnyComponent:
                {
                    parsedElement.ReferenceTypeId = ReferenceTypeIds.Aggregates;
                    break;
                }

                case RelativePathFormatter.ElementType.ForwardReference:
                {
                    parsedElement.ReferenceTypeId = typeTree.FindReferenceType(element.ReferenceTypeName);
                    break;
                }

                case RelativePathFormatter.ElementType.InverseReference:
                {
                    parsedElement.ReferenceTypeId = typeTree.FindReferenceType(element.ReferenceTypeName);
                    parsedElement.IsInverse       = true;
                    break;
                }
                }

                if (NodeId.IsNull(parsedElement.ReferenceTypeId))
                {
                    throw ServiceResultException.Create(
                              StatusCodes.BadSyntaxError,
                              "Could not convert BrowseName to a ReferenceTypeId: {0}",
                              element.ReferenceTypeName);
                }

                relativePath.Elements.Add(parsedElement);
            }

            return(relativePath);
        }
Пример #10
0
        /// <summary>
        /// Removes all of the references of the specified type and direction.
        /// </summary>
        /// <param name="referenceTypeId">The reference type identifier.</param>
        /// <param name="isInverse">if set to <c>true</c> this is inverse reference.</param>
        /// <returns>The result of removal.</returns>
        public bool RemoveAll(NodeId referenceTypeId, bool isInverse)
        {
            // check for null.
            if (NodeId.IsNull(referenceTypeId))
            {
                return(false);
            }

            // look up the reference type.
            ReferenceTypeEntry entry = null;

            if (!m_references.TryGetValue(referenceTypeId, out entry))
            {
                return(false);
            }

            if (isInverse)
            {
                if (entry.InverseTargets != null)
                {
                    foreach (LinkedListNode <KeyValuePair <IReference, T> > node in entry.InverseTargets.Values)
                    {
                        if (Object.ReferenceEquals(m_list, node.List))
                        {
                            m_list.Remove(node);
                        }

                        entry.InverseTargets = null;
                    }
                }

                if (entry.InverseExternalTargets != null)
                {
                    foreach (LinkedListNode <KeyValuePair <IReference, T> > node in entry.InverseExternalTargets.Values)
                    {
                        if (Object.ReferenceEquals(m_list, node.List))
                        {
                            m_list.Remove(node);
                        }
                    }

                    entry.InverseExternalTargets = null;
                }
            }
            else
            {
                if (entry.ForwardTargets != null)
                {
                    foreach (LinkedListNode <KeyValuePair <IReference, T> > node in entry.ForwardTargets.Values)
                    {
                        if (Object.ReferenceEquals(m_list, node.List))
                        {
                            m_list.Remove(node);
                        }
                    }

                    entry.ForwardTargets = null;
                }

                if (entry.ForwardExternalTargets != null)
                {
                    foreach (LinkedListNode <KeyValuePair <IReference, T> > node in entry.ForwardExternalTargets.Values)
                    {
                        if (Object.ReferenceEquals(m_list, node.List))
                        {
                            m_list.Remove(node);
                        }
                    }

                    entry.ForwardExternalTargets = null;
                }
            }

            // check for empty set.
            if (entry.IsEmpty)
            {
                m_references.Remove(referenceTypeId);
            }

            return(true);
        }
Пример #11
0
        /// <summary>
        /// Adds a node to the table (takes ownership of the object passed in).
        /// </summary>
        /// <param name="node">The node.</param>
        /// <remarks>
        /// Any existing node is removed.
        /// </remarks>
        public void Attach(ILocalNode node)
        {
            // remove duplicates.
            if (Exists(node.NodeId))
            {
                Remove(node.NodeId);
            }

            // check if importing a node from a XML source (must copy references from References array to ReferenceTable).
            Node serializedNode = node as Node;

            if (serializedNode != null && serializedNode.References.Count > 0 && serializedNode.ReferenceTable.Count == 0)
            {
                // index references.
                foreach (ReferenceNode reference in node.References)
                {
                    // ignore invalid references.
                    if (NodeId.IsNull(reference.ReferenceTypeId) || NodeId.IsNull(reference.TargetId))
                    {
                        continue;
                    }

                    node.References.Add(reference.ReferenceTypeId, reference.IsInverse, reference.TargetId);

                    // see if a remote node needs to be created.
                    if (reference.TargetId.ServerIndex != 0)
                    {
                        RemoteNode remoteNode = Find(reference.TargetId) as RemoteNode;

                        if (remoteNode == null)
                        {
                            remoteNode = new RemoteNode(this, reference.TargetId);
                            InternalAdd(remoteNode);
                        }

                        remoteNode.AddRef();
                    }
                }

                // clear unindexed reference list.
                node.References.Clear();
            }

            // add the node to the table.
            InternalAdd(node);

            // add reverse references.
            foreach (IReference reference in node.References)
            {
                ILocalNode targetNode = Find(reference.TargetId) as ILocalNode;

                if (targetNode == null)
                {
                    continue;
                }

                // type definition and modelling rule references are one way.
                if (reference.ReferenceTypeId != ReferenceTypeIds.HasTypeDefinition && reference.ReferenceTypeId != ReferenceTypeIds.HasModellingRule)
                {
                    targetNode.References.Add(reference.ReferenceTypeId, !reference.IsInverse, node.NodeId);
                }
            }

            // see if it is a type.
            if (m_typeTree != null)
            {
                m_typeTree.Add(node);
            }
        }
Пример #12
0
        /// <summary>
        /// Adds a set of nodes to the table.
        /// </summary>
        /// <param name="nodeSet">The node set.</param>
        /// <param name="externalReferences">The external references.</param>
        /// <returns></returns>
        public List <Node> Import(NodeSet nodeSet, IDictionary <NodeId, IList <IReference> > externalReferences)
        {
            List <Node> importedNodes = new List <Node>();

            if (nodeSet == null)
            {
                return(importedNodes);
            }

            // add the nodes.
            foreach (Node nodeToImport in nodeSet.Nodes)
            {
                // ignore empty nodes.
                if (nodeToImport == null || NodeId.IsNull(nodeToImport.NodeId))
                {
                    continue;
                }

                Node node = nodeSet.Copy(nodeToImport, m_namespaceUris, m_serverUris);

                // assign a browse name.
                if (QualifiedName.IsNull(node.BrowseName))
                {
                    node.BrowseName = new QualifiedName(node.NodeId.ToString(), 1);
                }

                // assign a display name.
                if (LocalizedText.IsNullOrEmpty(node.DisplayName))
                {
                    node.DisplayName = new LocalizedText(node.BrowseName.Name);
                }

                // index references (the node ids in the references were translated by the Copy() call above).
                foreach (ReferenceNode reference in node.References)
                {
                    // ignore invalid references.
                    if (NodeId.IsNull(reference.ReferenceTypeId) || NodeId.IsNull(reference.TargetId))
                    {
                        continue;
                    }

                    // ignore missing targets.
                    ExpandedNodeId targetId = reference.TargetId;

                    if (NodeId.IsNull(targetId))
                    {
                        continue;
                    }

                    // index reference.
                    node.ReferenceTable.Add(reference.ReferenceTypeId, reference.IsInverse, targetId);

                    // see if a remote node needs to be created.
                    if (targetId.ServerIndex != 0)
                    {
                        RemoteNode remoteNode = Find(targetId) as RemoteNode;

                        if (remoteNode == null)
                        {
                            remoteNode = new RemoteNode(this, targetId);
                            InternalAdd(remoteNode);
                        }

                        remoteNode.AddRef();
                    }
                }

                // clear imported references.
                node.References.Clear();

                // add the node.
                InternalAdd(node);
                importedNodes.Add(node);
            }

            // import the nodes.
            foreach (Node node in importedNodes)
            {
                // ignore invalid nodes.
                if (node == null || NodeId.IsNull(node.NodeId))
                {
                    continue;
                }

                // add reverse references.
                foreach (IReference reference in node.ReferenceTable)
                {
                    Node targetNode = Find(reference.TargetId) as Node;

                    if (targetNode == null)
                    {
                        if (reference.TargetId.ServerIndex != 0)
                        {
                            continue;
                        }

                        // return the reverse reference to a node outside the table.
                        if (externalReferences != null)
                        {
                            NodeId targetId = ExpandedNodeId.ToNodeId(reference.TargetId, m_namespaceUris);

                            if (targetId == null)
                            {
                                continue;
                            }

                            IList <IReference> referenceList = null;

                            if (!externalReferences.TryGetValue(targetId, out referenceList))
                            {
                                externalReferences[targetId] = referenceList = new List <IReference>();
                            }

                            ReferenceNode reverseReference = new ReferenceNode();

                            reverseReference.ReferenceTypeId = reference.ReferenceTypeId;
                            reverseReference.IsInverse       = !reference.IsInverse;
                            reverseReference.TargetId        = node.NodeId;

                            referenceList.Add(reverseReference);
                        }

                        continue;
                    }

                    // type definition and modelling rule references are one way.
                    if (reference.ReferenceTypeId != ReferenceTypeIds.HasTypeDefinition && reference.ReferenceTypeId != ReferenceTypeIds.HasModellingRule)
                    {
                        targetNode.ReferenceTable.Add(reference.ReferenceTypeId, !reference.IsInverse, node.NodeId);
                    }
                }

                // see if it is a type.
                if (m_typeTree != null)
                {
                    m_typeTree.Add(node);
                }
            }

            return(importedNodes);
        }
Пример #13
0
        /// <summary>
        /// Updates the nodeset string tables and returns a NodeId that references those tables.
        /// </summary>
        /// <param name="nodeId">The node identifier.</param>
        /// <param name="targetNamespaceUris">The target namespace URIs.</param>
        /// <param name="targetServerUris">The target server URIs.</param>
        /// <param name="sourceNamespaceUris">The source namespace URIs.</param>
        /// <param name="sourceServerUris">The source server URIs.</param>
        /// <returns>A NodeId that references those tables.</returns>
        private static ExpandedNodeId Translate(
            ExpandedNodeId nodeId,
            NamespaceTable targetNamespaceUris,
            StringTable targetServerUris,
            NamespaceTable sourceNamespaceUris,
            StringTable sourceServerUris)
        {
            if (targetNamespaceUris == null)
            {
                throw new ArgumentNullException("targetNamespaceUris");
            }
            if (sourceNamespaceUris == null)
            {
                throw new ArgumentNullException("sourceNamespaceUris");
            }

            if (nodeId.ServerIndex > 0)
            {
                if (targetServerUris == null)
                {
                    throw new ArgumentNullException("targetServerUris");
                }
                if (sourceServerUris == null)
                {
                    throw new ArgumentNullException("sourceServerUris");
                }
            }

            if (NodeId.IsNull(nodeId))
            {
                return(nodeId);
            }

            if (!nodeId.IsAbsolute)
            {
                return(Translate((NodeId)nodeId, targetNamespaceUris, sourceNamespaceUris));
            }

            string namespaceUri = nodeId.NamespaceUri;

            if (nodeId.ServerIndex > 0)
            {
                if (String.IsNullOrEmpty(namespaceUri))
                {
                    namespaceUri = sourceNamespaceUris.GetString(nodeId.NamespaceIndex);
                }

                string serverUri = sourceServerUris.GetString(nodeId.ServerIndex);

                int index = targetServerUris.GetIndex(serverUri);

                if (index == -1)
                {
                    index = targetServerUris.Append(serverUri);
                }

                return(new ExpandedNodeId(new NodeId(nodeId.Identifier, 0), namespaceUri, (uint)index));
            }

            ushort namespaceIndex = 0;

            if (!String.IsNullOrEmpty(namespaceUri))
            {
                int index = targetNamespaceUris.GetIndex(namespaceUri);

                if (index == -1)
                {
                    index = targetNamespaceUris.Append(namespaceUri);
                }

                namespaceIndex = (ushort)index;
            }

            return(new NodeId(nodeId.Identifier, namespaceIndex));
        }
Пример #14
0
        /// <summary>
        /// Returns the string representation of the embededobject.
        /// </summary>
        /// <param name="format">(Unused). Leave this as null</param>
        /// <param name="formatProvider">The provider of a mechanism for retrieving an object to control formatting.</param>
        /// <returns>
        /// A <see cref="T:System.String"/> containing the value of the current embeded instance in the specified format.
        /// </returns>
        /// <exception cref="FormatException">Thrown if the <i>format</i> parameter is not null</exception>
        public string ToString(string format, IFormatProvider formatProvider)
        {
            if (format == null)
            {
                if (m_body is byte[])
                {
                    return(String.Format(formatProvider, "Byte[{0}]", ((byte[])m_body).Length));
                }

                if (m_body is XmlElement)
                {
                    return(String.Format(formatProvider, "<{0}>", ((XmlElement)m_body).Name));
                }

                if (m_body is IEncodeable)
                {
                    StringBuilder body = new StringBuilder();

                    PropertyInfo[] properties = m_body.GetType().GetProperties(BindingFlags.Public | BindingFlags.FlattenHierarchy | BindingFlags.Instance);

                    foreach (PropertyInfo property in properties)
                    {
                        object[] attributes = property.GetCustomAttributes(typeof(DataMemberAttribute), true);

                        for (int ii = 0; ii < attributes.Length; ii++)
                        {
                            DataMemberAttribute contract = attributes[ii] as DataMemberAttribute;

                            if (contract != null)
                            {
                                if (body.Length == 0)
                                {
                                    body.Append("{");
                                }
                                else
                                {
                                    body.Append(" | ");
                                }

                                body.AppendFormat("{0}", property.GetGetMethod().Invoke(m_body, null));
                            }
                        }
                    }

                    if (body.Length > 0)
                    {
                        body.Append("}");
                    }

                    return(String.Format(formatProvider, "{0}", body));
                }

                if (!NodeId.IsNull(this.m_typeId))
                {
                    return(String.Format(formatProvider, "{{{0}}}", this.m_typeId));
                }

                return("(null)");
            }

            throw new FormatException(Utils.Format("Invalid format string: '{0}'.", format));
        }