Opc.Ua.BinaryDecoder.ReadVariant C# (CSharp) Method

ReadVariant() private method

private ReadVariant ( string fieldName ) : Variant
fieldName string
return Variant
        public Variant ReadVariant(string fieldName)
        {
            // read the encoding byte.
            byte encodingByte = m_reader.ReadByte();

            Variant value = new Variant();

            if ((encodingByte & (byte)VariantArrayEncodingBits.Array) != 0)
            {
                // read the array length.
                int length = m_reader.ReadInt32();

                if (length < 0)
                {
                    return value;
                }

                Array array = null;

                BuiltInType builtInType = (BuiltInType)(encodingByte & (byte)VariantArrayEncodingBits.TypeMask);
                
                switch (builtInType)
                {
                    case BuiltInType.Boolean:
                    {
                        bool[] values = new bool[length];

                        for (int ii = 0; ii < values.Length; ii++)
                        {
                            values[ii] = ReadBoolean(null);
                        }
                        
                        array = values;
                        break;
                    }

                    case BuiltInType.SByte:
                    {
                        sbyte[] values = new sbyte[length];

                        for (int ii = 0; ii < values.Length; ii++)
                        {
                            values[ii] = ReadSByte(null);
                        }
                        
                        array = values;
                        break;
                    }

                    case BuiltInType.Byte:
                    {
                        byte[] values = new byte[length];

                        for (int ii = 0; ii < values.Length; ii++)
                        {
                            values[ii] = ReadByte(null);
                        }

                        array = values;
                        break;
                    }

                    case BuiltInType.Int16:
                    {
                        short[] values = new short[length];

                        for (int ii = 0; ii < values.Length; ii++)
                        {
                            values[ii] = ReadInt16(null);
                        }
                        
                        array = values;
                        break;
                    }

                    case BuiltInType.UInt16:
                    {
                        ushort[] values = new ushort[length];

                        for (int ii = 0; ii < values.Length; ii++)
                        {
                            values[ii] = ReadUInt16(null);
                        }
                        
                        array = values;
                        break;
                    }

                    case BuiltInType.Int32:
                    case BuiltInType.Enumeration:
                    {
                        int[] values = new int[length];

                        for (int ii = 0; ii < values.Length; ii++)
                        {
                            values[ii] = ReadInt32(null);
                        }
                        
                        array = values;
                        break;
                    }

                    case BuiltInType.UInt32:
                    {
                        uint[] values = new uint[length];

                        for (int ii = 0; ii < values.Length; ii++)
                        {
                            values[ii] = ReadUInt32(null);
                        }
                        
                        array = values;
                        break;
                    }

                    case BuiltInType.Int64:
                    {
                        long[] values = new long[length];

                        for (int ii = 0; ii < values.Length; ii++)
                        {
                            values[ii] = ReadInt64(null);
                        }
                        
                        array = values;
                        break;
                    }

                    case BuiltInType.UInt64:
                    {
                        ulong[] values = new ulong[length];

                        for (int ii = 0; ii < values.Length; ii++)
                        {
                            values[ii] = ReadUInt64(null);
                        }
                        
                        array = values;
                        break;
                    }

                    case BuiltInType.Float:
                    {
                        float[] values = new float[length];

                        for (int ii = 0; ii < values.Length; ii++)
                        {
                            values[ii] = ReadFloat(null);
                        }
                        
                        array = values;
                        break;
                    }

                    case BuiltInType.Double:
                    {
                        double[] values = new double[length];

                        for (int ii = 0; ii < values.Length; ii++)
                        {
                            values[ii] = ReadDouble(null);
                        }
                        
                        array = values;
                        break;
                    }

                    case BuiltInType.String:
                    {
                        string[] values = new string[length];

                        for (int ii = 0; ii < values.Length; ii++)
                        {
                            values[ii] = ReadString(null);
                        }
                        
                        array = values;
                        break;
                    }

                    case BuiltInType.DateTime:
                    {
                        DateTime[] values = new DateTime[length];

                        for (int ii = 0; ii < values.Length; ii++)
                        {
                            values[ii] = ReadDateTime(null);
                        }
                        
                        array = values;
                        break;
                    }

                    case BuiltInType.Guid:
                    {
                        Uuid[] values = new Uuid[length];

                        for (int ii = 0; ii < values.Length; ii++)
                        {
                            values[ii] = ReadGuid(null);
                        }
                        
                        array = values;
                        break;
                    }

                    case BuiltInType.ByteString:
                    {
                        byte[][] values = new byte[length][];

                        for (int ii = 0; ii < values.Length; ii++)
                        {
                            values[ii] = ReadByteString(null);
                        }
                        
                        array = values;
                        break;
                    }

                    case BuiltInType.XmlElement:
                    {
                        try
                        {
                            XmlElement[] values = new XmlElement[length];

                            for (int ii = 0; ii < values.Length; ii++)
                            {
                                values[ii] = ReadXmlElement(null);
                            }

                            array = values;
                        }
                        catch(Exception ex)
                        {
                            Utils.Trace(ex, "Error reading variant.");
                        }

                        break;
                    }
                        
                    case BuiltInType.NodeId:
                    {
                        NodeId[] values = new NodeId[length];

                        for (int ii = 0; ii < values.Length; ii++)
                        {
                            values[ii] = ReadNodeId(null);
                        }
                        
                        array = values;
                        break;
                    }
                        
                    case BuiltInType.ExpandedNodeId:
                    {
                        ExpandedNodeId[] values = new ExpandedNodeId[length];

                        for (int ii = 0; ii < values.Length; ii++)
                        {
                            values[ii] = ReadExpandedNodeId(null);
                        }
                        
                        array = values;
                        break;
                    }
                        
                    case BuiltInType.StatusCode:
                    {
                        StatusCode[] values = new StatusCode[length];

                        for (int ii = 0; ii < values.Length; ii++)
                        {
                            values[ii] = ReadStatusCode(null);
                        }
                        
                        array = values;
                        break;
                    }
                        
                    case BuiltInType.QualifiedName:
                    {
                        QualifiedName[] values = new QualifiedName[length];

                        for (int ii = 0; ii < values.Length; ii++)
                        {
                            values[ii] = ReadQualifiedName(null);
                        }
                        
                        array = values;
                        break;
                    }
                        
                    case BuiltInType.LocalizedText:
                    {
                        LocalizedText[] values = new LocalizedText[length];

                        for (int ii = 0; ii < values.Length; ii++)
                        {
                            values[ii] = ReadLocalizedText(null);
                        }
                        
                        array = values;
                        break;
                    }
                        
                    case BuiltInType.ExtensionObject:
                    {
                        ExtensionObject[] values = new ExtensionObject[length];

                        for (int ii = 0; ii < values.Length; ii++)
                        {
                            values[ii] = ReadExtensionObject();
                        }
                        
                        array = values;
                        break;
                    }
                        
                    case BuiltInType.DataValue:
                    {
                        DataValue[] values = new DataValue[length];

                        for (int ii = 0; ii < values.Length; ii++)
                        {
                            values[ii] = ReadDataValue(null);
                        }
                        
                        array = values;
                        break;
                    }
                        
                    case BuiltInType.Variant:
                    {
                        Variant[] values = new Variant[length];

                        for (int ii = 0; ii < values.Length; ii++)
                        {
                            values[ii] = ReadVariant(null);
                        }
                        
                        array = values;
                        break;
                    }

                    default:
                    {
                        throw new ServiceResultException(
                            StatusCodes.BadDecodingError,
                            Utils.Format("Cannot decode unknown type in Variant object (0x{0:X2}).", encodingByte)); 
                    }
                }

                if (array == null)
                {
                    value = new Variant(StatusCodes.BadEncodingError);
                }
                else
                {
                    // check for multi-dimensional arrays.
                    if ((encodingByte & (byte)VariantArrayEncodingBits.ArrayDimensions) != 0)
                    {
                        Int32Collection dimensions = ReadInt32Array(null);

                        // check if ArrayDimensions are consistent with the ArrayLength.
                        if (dimensions == null || dimensions.Count == 0)
                        {
                            throw new ServiceResultException(
                                StatusCodes.BadDecodingError, 
                                "ArrayDimensions not specified when ArrayDimensions encoding bit was set in Variant object.");
                        }

                        int[] dimensionsArray = dimensions.ToArray();
                        int matrixLength = 1;

                        for (int ii = 0; ii < dimensionsArray.Length; ii++)
                        {
                            if (dimensionsArray[ii] == 0 && length >0)
                            {
                                throw new ServiceResultException(
                                    StatusCodes.BadDecodingError,
                                    Utils.Format("ArrayDimensions [{0}] is zero in Variant object.", ii)); 
                            }

                            matrixLength *= dimensionsArray[ii];
                        }

                        if (matrixLength != length)
                        {
                            throw new ServiceResultException(StatusCodes.BadDecodingError, "ArrayDimensions does not match with the ArrayLength in Variant object.");
                        }

                        value = new Variant(new Matrix(array, builtInType, dimensions.ToArray()));
                    }
                    else
                    {
                        value = new Variant(array);
                    }
                }
            }

            else
            {
                switch ((BuiltInType)encodingByte)
                {
                    case BuiltInType.Null:
                    {
                        value.Value = null;
                        break;
                    }

                    case BuiltInType.Boolean:
                    {
                        value.Set(ReadBoolean(null));
                        break;
                    }

                    case BuiltInType.SByte:
                    {
                        value.Set(ReadSByte(null));
                        break;
                    }

                    case BuiltInType.Byte:
                    {
                        value.Set(ReadByte(null));
                        break;
                    }

                    case BuiltInType.Int16:
                    {
                        value.Set(ReadInt16(null));
                        break;
                    }

                    case BuiltInType.UInt16:
                    {
                        value.Set(ReadUInt16(null));
                        break;
                    }

                    case BuiltInType.Int32:
                    case BuiltInType.Enumeration:
                    {
                        value.Set(ReadInt32(null));
                        break;
                    }

                    case BuiltInType.UInt32:
                    {
                        value.Set(ReadUInt32(null));
                        break;
                    }

                    case BuiltInType.Int64:
                    {
                        value.Set(ReadInt64(null));
                        break;
                    }

                    case BuiltInType.UInt64:
                    {
                        value.Set(ReadUInt64(null));
                        break;
                    }

                    case BuiltInType.Float:
                    {
                        value.Set(ReadFloat(null));
                        break;
                    }

                    case BuiltInType.Double:
                    {
                        value.Set(ReadDouble(null));
                        break;
                    }

                    case BuiltInType.String:
                    {
                        value.Set(ReadString(null));
                        break;
                    }

                    case BuiltInType.DateTime:
                    {
                        value.Set(ReadDateTime(null));
                        break;
                    }

                    case BuiltInType.Guid:
                    {
                        value.Set(ReadGuid(null));
                        break;
                    }

                    case BuiltInType.ByteString:
                    {
                        value.Set(ReadByteString(null));
                        break;
                    }

                    case BuiltInType.XmlElement:
                    {
                        try
                        {
                            value.Set(ReadXmlElement(null));
                        }
                        catch(Exception ex)
                        {
                            Utils.Trace(ex, "Error reading xml element for variant.");
                            value.Set(StatusCodes.BadEncodingError);
                        }                        
                        break;
                    }

                    case BuiltInType.NodeId:
                    {
                        value.Set(ReadNodeId(null));
                        break;
                    }

                    case BuiltInType.ExpandedNodeId:
                    {
                        value.Set(ReadExpandedNodeId(null));
                        break;
                    }
                        
                    case BuiltInType.StatusCode:
                    {
                        value.Set(ReadStatusCode(null));
                        break;
                    }

                    case BuiltInType.QualifiedName:
                    {
                        value.Set(ReadQualifiedName(null));
                        break;
                    }

                    case BuiltInType.LocalizedText:
                    {
                        value.Set(ReadLocalizedText(null));
                        break;
                    }

                    case BuiltInType.ExtensionObject:
                    {
                        value.Set(ReadExtensionObject());
                        break;
                    }

                    case BuiltInType.DataValue:
                    {
                        value.Set(ReadDataValue(null));
                        break;
                    }

                    default:
                    {
                        throw new ServiceResultException(
                            StatusCodes.BadDecodingError,
                            Utils.Format("Cannot decode unknown type in Variant object (0x{0:X2}).", encodingByte)); 
                    }
                }
            }

            return value;
        }

Usage Example

        /// <summary>
        /// Updates the specified context.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="decoder">The decoder.</param>
        /// <param name="attibutesToLoad">The attributes to load.</param>
        public override void Update(ISystemContext context, BinaryDecoder decoder, AttributesToSave attibutesToLoad)
        {
            base.Update(context, decoder, attibutesToLoad);

            if ((attibutesToLoad & AttributesToSave.Value) != 0)
            {
                WrappedValue = decoder.ReadVariant(null);
            }

            if ((attibutesToLoad & AttributesToSave.DataType) != 0)
            {
                m_dataType = decoder.ReadNodeId(null);
            }

            if ((attibutesToLoad & AttributesToSave.ValueRank) != 0)
            {
                m_valueRank = decoder.ReadInt32(null);
            }

            if ((attibutesToLoad & AttributesToSave.ArrayDimensions) != 0)
            {
                UInt32Collection arrayDimensions = decoder.ReadUInt32Array(null);

                if (arrayDimensions != null && arrayDimensions.Count > 0)
                {
                    m_arrayDimensions = new ReadOnlyList<uint>(arrayDimensions);
                }
                else
                {
                    m_arrayDimensions = null;
                }
            }
        }