From e606f3aa8ca515ef1432af2be8b0e8697f91dbf2 Mon Sep 17 00:00:00 2001 From: Martin Regen Date: Wed, 19 Feb 2020 13:34:55 +0100 Subject: [PATCH] Stabilize TCP receive (#904) - Various issues found during server testing with ref server - Take a different approach on the nesting issue - Fix a duplicate buffer free issue - stabilize binary decoder --- .../SDK/Opc.Ua.Client/Session.cs | 6 +- .../Reference/Server/ReferenceNodeManager.cs | 4 +- .../Stack/State/BaseVariableState.cs | 6 +- .../Opc.Ua.Core/Stack/Tcp/TcpMessageSocket.cs | 233 ++-- .../Opc.Ua.Core/Stack/Tcp/TcpServerChannel.cs | 2 +- .../Stack/Tcp/UaSCBinaryChannel.cs | 14 +- .../Types/Encoders/BinaryDecoder.cs | 2 +- .../Opc.Ua.Core/Types/Utils/DataGenerator.cs | 3 +- Stack/Opc.Ua.Core/Types/Utils/TypeInfo.cs | 1113 ++++++++--------- 9 files changed, 684 insertions(+), 699 deletions(-) diff --git a/SampleApplications/SDK/Opc.Ua.Client/Session.cs b/SampleApplications/SDK/Opc.Ua.Client/Session.cs index 0e579a58f3..634db31adc 100644 --- a/SampleApplications/SDK/Opc.Ua.Client/Session.cs +++ b/SampleApplications/SDK/Opc.Ua.Client/Session.cs @@ -355,7 +355,7 @@ namespace Opc.Ua.Client bool isLocalHost = false; if (endpoint.EndpointUrl.HostNameType == UriHostNameType.Dns) { - if (dnsHostName.ToLowerInvariant() == "localhost") + if (String.Equals(dnsHostName, "localhost", StringComparison.InvariantCultureIgnoreCase)) { isLocalHost = true; } @@ -382,8 +382,8 @@ namespace Opc.Ua.Client for (int ii = 0; ii < domains.Count; ii++) { - if (String.Compare(hostname, domains[ii], StringComparison.OrdinalIgnoreCase) == 0 || - String.Compare(dnsHostName, domains[ii], StringComparison.OrdinalIgnoreCase) == 0) + if (String.Equals(hostname, domains[ii], StringComparison.OrdinalIgnoreCase) || + String.Equals(dnsHostName, domains[ii], StringComparison.OrdinalIgnoreCase)) { domainFound = true; break; diff --git a/SampleApplications/Workshop/Reference/Server/ReferenceNodeManager.cs b/SampleApplications/Workshop/Reference/Server/ReferenceNodeManager.cs index 829c53e6da..464912791c 100644 --- a/SampleApplications/Workshop/Reference/Server/ReferenceNodeManager.cs +++ b/SampleApplications/Workshop/Reference/Server/ReferenceNodeManager.cs @@ -1,4 +1,4 @@ -/* ======================================================================== +/* ======================================================================== * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 @@ -570,7 +570,7 @@ namespace Quickstarts.ReferenceServer CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "LocalizedText", "LocalizedText", BuiltInType.LocalizedText, ValueRanks.OneDimension, new LocalizedText[] { new LocalizedText("en", "Hello World1"), new LocalizedText("en", "Hello World2"), new LocalizedText("en", "Hello World3"), new LocalizedText("en", "Hello World4"), new LocalizedText("en", "Hello World5"), new LocalizedText("en", "Hello World6"), new LocalizedText("en", "Hello World7"), new LocalizedText("en", "Hello World8"), new LocalizedText("en", "Hello World9"), new LocalizedText("en", "Hello World10") }); CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "NodeId", "NodeId", BuiltInType.NodeId, ValueRanks.OneDimension, new NodeId[] { new NodeId(Guid.NewGuid()), new NodeId(Guid.NewGuid()), new NodeId(Guid.NewGuid()), new NodeId(Guid.NewGuid()), new NodeId(Guid.NewGuid()), new NodeId(Guid.NewGuid()), new NodeId(Guid.NewGuid()), new NodeId(Guid.NewGuid()), new NodeId(Guid.NewGuid()), new NodeId(Guid.NewGuid()) }); CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "Number", "Number", BuiltInType.Number, ValueRanks.OneDimension, new Int16[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); - CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "QualifiedName", "QualifiedName", BuiltInType.QualifiedName, ValueRanks.OneDimension, new Int16[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); + CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "QualifiedName", "QualifiedName", BuiltInType.QualifiedName, ValueRanks.OneDimension, new QualifiedName[] { "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9"}); CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "SByte", "SByte", BuiltInType.SByte, ValueRanks.OneDimension, new SByte[] { 10, 20, 30, 40, 50, 60, 70, 80, 90 }); CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "String", "String", BuiltInType.String, ValueRanks.OneDimension, new String[] { "a00", "b10", "c20", "d30", "e40", "f50", "g60", "h70", "i80", "j90" }); CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "Time", "Time", DataTypeIds.Time, ValueRanks.OneDimension, new String[] { DateTime.MinValue.ToString(), DateTime.MaxValue.ToString(), DateTime.MinValue.ToString(), DateTime.MaxValue.ToString(), DateTime.MinValue.ToString(), DateTime.MaxValue.ToString(), DateTime.MinValue.ToString(), DateTime.MaxValue.ToString(), DateTime.MinValue.ToString(), DateTime.MaxValue.ToString() }, null); diff --git a/Stack/Opc.Ua.Core/Stack/State/BaseVariableState.cs b/Stack/Opc.Ua.Core/Stack/State/BaseVariableState.cs index cd6b311a13..c810ac42f0 100644 --- a/Stack/Opc.Ua.Core/Stack/State/BaseVariableState.cs +++ b/Stack/Opc.Ua.Core/Stack/State/BaseVariableState.cs @@ -1930,7 +1930,11 @@ namespace Opc.Ua return (StatusCode)(uint)value; } } - return StatusCodes.BadTypeMismatch; + // test for special case Null type + if (!(m_dataType.IsNullNodeId && value == null)) + { + return StatusCodes.BadTypeMismatch; + } } value = ExtractValueFromVariant(context, value, true); diff --git a/Stack/Opc.Ua.Core/Stack/Tcp/TcpMessageSocket.cs b/Stack/Opc.Ua.Core/Stack/Tcp/TcpMessageSocket.cs index 2f9868caea..eb7f519c5a 100644 --- a/Stack/Opc.Ua.Core/Stack/Tcp/TcpMessageSocket.cs +++ b/Stack/Opc.Ua.Core/Stack/Tcp/TcpMessageSocket.cs @@ -52,8 +52,7 @@ namespace Opc.Ua.Bindings { public TcpMessageSocketAsyncEventArgs() { - m_args = new SocketAsyncEventArgs - { + m_args = new SocketAsyncEventArgs { UserToken = this }; } @@ -68,11 +67,7 @@ namespace Opc.Ua.Bindings } #endregion - public object UserToken - { - get { return m_userToken; } - set { m_userToken = value; } - } + public object UserToken { get; set; } public void SetBuffer(byte[] buffer, int offset, int count) { @@ -117,7 +112,6 @@ namespace Opc.Ua.Bindings } public SocketAsyncEventArgs m_args; - private object m_userToken; private event EventHandler m_internalComplete; } @@ -140,11 +134,7 @@ namespace Opc.Ua.Bindings } #endregion - public object UserToken - { - get { return m_UserToken; } - set { m_UserToken = value; } - } + public object UserToken { get; set; } public void SetBuffer(byte[] buffer, int offset, int count) { @@ -181,7 +171,6 @@ namespace Opc.Ua.Bindings } private SocketError m_socketError; - private object m_UserToken; } @@ -236,7 +225,8 @@ namespace Opc.Ua.Bindings m_bufferManager = bufferManager; m_receiveBufferSize = receiveBufferSize; m_incomingMessageSize = -1; - m_ReadComplete = new EventHandler(OnReadComplete); + m_readComplete = new EventHandler(OnReadComplete); + m_readState = ReadState.Ready; } /// @@ -263,7 +253,7 @@ namespace Opc.Ua.Bindings m_bufferManager = bufferManager; m_receiveBufferSize = receiveBufferSize; m_incomingMessageSize = -1; - m_ReadComplete = new EventHandler(OnReadComplete); + m_readComplete = new EventHandler(OnReadComplete); } #endregion @@ -293,18 +283,7 @@ namespace Opc.Ua.Bindings /// Gets the socket handle. /// /// The socket handle. - public int Handle - { - get - { - if (m_socket != null) - { - return m_socket.GetHashCode(); - } - - return -1; - } - } + public int Handle => m_socket != null ? m_socket.GetHashCode() : -1; /// /// Connects to an endpoint. @@ -327,7 +306,7 @@ namespace Opc.Ua.Bindings try { // Get DNS host information - hostAdresses = await Dns.GetHostAddressesAsync(endpointUrl.DnsSafeHost); + hostAdresses = await Dns.GetHostAddressesAsync(endpointUrl.DnsSafeHost).ConfigureAwait(false); } catch (SocketException e) { @@ -397,12 +376,12 @@ namespace Opc.Ua.Bindings if (moreAddresses && !m_tcs.Task.IsCompleted) { - await Task.Delay(1000); + await Task.Delay(1000).ConfigureAwait(false); } if (!moreAddresses || m_tcs.Task.IsCompleted) { - error = await m_tcs.Task; + error = await m_tcs.Task.ConfigureAwait(false); switch (error) { case SocketError.Success: @@ -415,7 +394,7 @@ namespace Opc.Ua.Bindings } } while (moreAddresses); - ErrorExit: + ErrorExit: doCallback(error); return false; @@ -459,30 +438,27 @@ namespace Opc.Ua.Bindings /// Starts reading messages from the socket. /// public void ReadNextMessage() - { - var args = InternalReadNextMessage(); - if (args != null) - { - m_ReadComplete(null, args); - } - } - - private SocketAsyncEventArgs InternalReadNextMessage() { lock (m_readLock) { - // allocate a buffer large enough to a message chunk. - if (m_receiveBuffer == null) + do { - m_receiveBuffer = m_bufferManager.TakeBuffer(m_receiveBufferSize, "ReadNextMessage"); - } + // allocate a buffer large enough to a message chunk. + if (m_receiveBuffer == null) + { + m_receiveBuffer = m_bufferManager.TakeBuffer(m_receiveBufferSize, "ReadNextMessage"); + } - // read the first 8 bytes of the message which contains the message size. - m_bytesReceived = 0; - m_bytesToReceive = TcpMessageLimits.MessageTypeAndSize; - m_incomingMessageSize = -1; + // read the first 8 bytes of the message which contains the message size. + m_bytesReceived = 0; + m_bytesToReceive = TcpMessageLimits.MessageTypeAndSize; + m_incomingMessageSize = -1; - return ReadNextBlock(); + do + { + ReadNextBlock(); + } while (m_readState == ReadState.ReadNextBlock); + } while (m_readState == ReadState.ReadNextMessage); } } @@ -508,50 +484,13 @@ namespace Opc.Ua.Bindings try { + bool innerCall = m_readState == ReadState.ReadComplete; error = DoReadComplete(e); - - while (ServiceResult.IsGood(error) && e != null) + // to avoid recursion, inner calls of OnReadComplete return + // after processing the ReadComplete and let the outer call handle it + if (!innerCall && !ServiceResult.IsBad(error)) { - e.Dispose(); - - // check if more data left to read. - if (m_bytesReceived < m_bytesToReceive) - { - e = ReadNextBlock(); - } - // start reading the message body. - else if (m_incomingMessageSize < 0) - { - m_incomingMessageSize = BitConverter.ToInt32(m_receiveBuffer, 4); - - if (m_incomingMessageSize <= 0 || m_incomingMessageSize > m_receiveBufferSize) - { - Utils.Trace( - "BadTcpMessageTooLarge: BufferSize={0}; MessageSize={1}", - m_receiveBufferSize, - m_incomingMessageSize); - - error = ServiceResult.Create( - StatusCodes.BadTcpMessageTooLarge, - "Messages size {1} bytes is too large for buffer of size {0}.", - m_receiveBufferSize, - m_incomingMessageSize); - } - - // set up buffer for reading the message body. - m_bytesToReceive = m_incomingMessageSize; - - e = ReadNextBlock(); - } - else - { - e = InternalReadNextMessage(); - } - - if(e != null) - { - error = DoReadComplete(e); - } + while (ReadNext()) ; } } catch (Exception ex) @@ -572,10 +511,7 @@ namespace Opc.Ua.Bindings m_receiveBuffer = null; } - if (m_sink != null) - { - m_sink.OnReceiveError(this, error); - } + m_sink?.OnReceiveError(this, error); } } } @@ -587,6 +523,7 @@ namespace Opc.Ua.Bindings { // complete operation. int bytesRead = e.BytesTransferred; + m_readState = ReadState.Ready; lock (m_socketLock) { @@ -606,6 +543,7 @@ namespace Opc.Ua.Bindings m_receiveBuffer = null; } + m_readState = ReadState.Error; return ServiceResult.Create(StatusCodes.BadConnectionClosed, "Remote side closed connection"); } @@ -614,12 +552,36 @@ namespace Opc.Ua.Bindings // check if more data left to read. if (m_bytesReceived < m_bytesToReceive) { + m_readState = ReadState.ReadNextBlock; return ServiceResult.Good; } // start reading the message body. if (m_incomingMessageSize < 0) { + m_incomingMessageSize = BitConverter.ToInt32(m_receiveBuffer, 4); + + if (m_incomingMessageSize <= 0 || m_incomingMessageSize > m_receiveBufferSize) + { + Utils.Trace( + "BadTcpMessageTooLarge: BufferSize={0}; MessageSize={1}", + m_receiveBufferSize, + m_incomingMessageSize); + + m_readState = ReadState.Error; + + return ServiceResult.Create( + StatusCodes.BadTcpMessageTooLarge, + "Messages size {1} bytes is too large for buffer of size {0}.", + m_receiveBufferSize, + m_incomingMessageSize); + } + + // set up buffer for reading the message body. + m_bytesToReceive = m_incomingMessageSize; + + m_readState = ReadState.ReadNextBlock; + return ServiceResult.Good; } @@ -649,13 +611,16 @@ namespace Opc.Ua.Bindings m_receiveBuffer = null; } + // start receiving next message. + m_readState = ReadState.ReadNextMessage; + return ServiceResult.Good; } /// /// Reads the next block of data from the socket. /// - private SocketAsyncEventArgs ReadNextBlock() + private void ReadNextBlock() { Socket socket = null; @@ -669,8 +634,8 @@ namespace Opc.Ua.Bindings m_bufferManager.ReturnBuffer(m_receiveBuffer, "ReadNextBlock"); m_receiveBuffer = null; } - - return null; + m_readState = ReadState.NotConnected; + return; } socket = m_socket; @@ -678,19 +643,19 @@ namespace Opc.Ua.Bindings // avoid stale ServiceException when socket is disconnected if (!socket.Connected) { - return null; + m_readState = ReadState.NotConnected; + return; } - } BufferManager.LockBuffer(m_receiveBuffer); - ServiceResult error = ServiceResult.Good; - SocketAsyncEventArgs args = new SocketAsyncEventArgs(); + var args = new SocketAsyncEventArgs(); try { + m_readState = ReadState.Receive; args.SetBuffer(m_receiveBuffer, m_bytesReceived, m_bytesToReceive - m_bytesReceived); - args.Completed += m_ReadComplete; + args.Completed += m_readComplete; if (!socket.ReceiveAsync(args)) { // I/O completed synchronously @@ -698,28 +663,38 @@ namespace Opc.Ua.Bindings { throw ServiceResultException.Create(StatusCodes.BadTcpInternalError, args.SocketError.ToString()); } - else - { - return args; - //Root of the problem - //m_ReadComplete(null, args); - } + // set state to inner complete + m_readState = ReadState.ReadComplete; + m_readComplete(null, args); } } catch (ServiceResultException) { - args.Dispose(); + args?.Dispose(); BufferManager.UnlockBuffer(m_receiveBuffer); throw; } catch (Exception ex) { - args.Dispose(); + args?.Dispose(); BufferManager.UnlockBuffer(m_receiveBuffer); throw ServiceResultException.Create(StatusCodes.BadTcpInternalError, ex, "BeginReceive failed."); } + } - return null; + /// + /// Helper to read read next block or message based on current state. + /// + private bool ReadNext() + { + bool result = true; + switch (m_readState) + { + case ReadState.ReadNextBlock: ReadNextBlock(); break; + case ReadState.ReadNextMessage: ReadNextMessage(); break; + default: result = false; break; + } + return result; } /// @@ -737,12 +712,11 @@ namespace Opc.Ua.Bindings private SocketError BeginConnect(IPAddress address, AddressFamily addressFamily, int port, CallbackAction callback) { var socket = new Socket(addressFamily, SocketType.Stream, ProtocolType.Tcp); - var args = new SocketAsyncEventArgs() - { + var args = new SocketAsyncEventArgs() { UserToken = callback, RemoteEndPoint = new IPEndPoint(address, port), }; - args.Completed += new EventHandler(OnSocketConnected); + args.Completed += OnSocketConnected; if (!socket.ConnectAsync(args)) { // I/O completed synchronously @@ -804,6 +778,7 @@ namespace Opc.Ua.Bindings args.Dispose(); } #endregion + #region Write Handling /// /// Sends a buffer. @@ -823,29 +798,45 @@ namespace Opc.Ua.Bindings return m_socket.SendAsync(eventArgs.m_args); } #endregion + #region Event factory public IMessageSocketAsyncEventArgs MessageSocketEventArgs() { return new TcpMessageSocketAsyncEventArgs(); } #endregion + #region Private Fields private IMessageSink m_sink; private BufferManager m_bufferManager; - private int m_receiveBufferSize; - private EventHandler m_ReadComplete; + private readonly int m_receiveBufferSize; + private readonly EventHandler m_readComplete; - private object m_socketLock = new object(); + private readonly object m_socketLock = new object(); private Socket m_socket; - private bool m_closed = false; + private bool m_closed; private TaskCompletionSource m_tcs; private int m_socketResponses; - private object m_readLock = new object(); + /// + /// States for the nested read handler. + /// + private enum ReadState + { + Ready = 0, + ReadNextMessage = 1, + ReadNextBlock = 2, + Receive = 3, + ReadComplete = 4, + NotConnected = 5, + Error = 0xff + }; + private readonly object m_readLock = new object(); private byte[] m_receiveBuffer; private int m_bytesReceived; private int m_bytesToReceive; private int m_incomingMessageSize; + private ReadState m_readState; #endregion } } diff --git a/Stack/Opc.Ua.Core/Stack/Tcp/TcpServerChannel.cs b/Stack/Opc.Ua.Core/Stack/Tcp/TcpServerChannel.cs index 903c7c1d0f..319a982ef1 100644 --- a/Stack/Opc.Ua.Core/Stack/Tcp/TcpServerChannel.cs +++ b/Stack/Opc.Ua.Core/Stack/Tcp/TcpServerChannel.cs @@ -1208,7 +1208,7 @@ namespace Opc.Ua.Bindings { Utils.Trace(e, "Unexpected error processing request."); SendServiceFault(token, requestId, ServiceResult.Create(e, StatusCodes.BadTcpInternalError, "Unexpected error processing request.")); - return false; + return true; } finally { diff --git a/Stack/Opc.Ua.Core/Stack/Tcp/UaSCBinaryChannel.cs b/Stack/Opc.Ua.Core/Stack/Tcp/UaSCBinaryChannel.cs index dd8e2e8bec..399fa128c1 100644 --- a/Stack/Opc.Ua.Core/Stack/Tcp/UaSCBinaryChannel.cs +++ b/Stack/Opc.Ua.Core/Stack/Tcp/UaSCBinaryChannel.cs @@ -208,12 +208,8 @@ namespace Opc.Ua.Bindings /// protected void ChannelStateChanged(TcpChannelState state, ServiceResult reason) { - Task.Run(() => - { - if (m_StateChanged != null) - { - m_StateChanged(this, state, reason); - } + Task.Run(() => { + m_StateChanged?.Invoke(this, state, reason); }); } @@ -389,7 +385,6 @@ namespace Opc.Ua.Bindings lock (DataLock) { ServiceResult error = ServiceResult.Good; - try { Utils.TraceDebug("Bytes written: {0}", e.BytesTransferred); @@ -406,6 +401,11 @@ namespace Opc.Ua.Bindings } catch (Exception ex) { + if (ex is InvalidOperationException) + { + // suppress chained exception in HandleWriteComplete/ReturnBuffer + e.BufferList = null; + } error = ServiceResult.Create(ex, StatusCodes.BadTcpInternalError, "Unexpected error during write operation."); HandleWriteComplete((BufferCollection)e.BufferList, e.UserToken, e.BytesTransferred, error); } diff --git a/Stack/Opc.Ua.Core/Types/Encoders/BinaryDecoder.cs b/Stack/Opc.Ua.Core/Types/Encoders/BinaryDecoder.cs index 79aec38e30..db34978702 100644 --- a/Stack/Opc.Ua.Core/Types/Encoders/BinaryDecoder.cs +++ b/Stack/Opc.Ua.Core/Types/Encoders/BinaryDecoder.cs @@ -1591,7 +1591,7 @@ namespace Opc.Ua if (encodeable == null) { // figure out how long the object is. - if (length == -1) + if (length < 0) { throw new ServiceResultException( StatusCodes.BadDecodingError, diff --git a/Stack/Opc.Ua.Core/Types/Utils/DataGenerator.cs b/Stack/Opc.Ua.Core/Types/Utils/DataGenerator.cs index 1ff6b5e2e4..5926aa9030 100644 --- a/Stack/Opc.Ua.Core/Types/Utils/DataGenerator.cs +++ b/Stack/Opc.Ua.Core/Types/Utils/DataGenerator.cs @@ -373,7 +373,8 @@ namespace Opc.Ua.Test if (value != null) { - if (expectedType == BuiltInType.Guid) + if (expectedType == BuiltInType.Guid && + value is Guid) { value = new Uuid((Guid)value); } diff --git a/Stack/Opc.Ua.Core/Types/Utils/TypeInfo.cs b/Stack/Opc.Ua.Core/Types/Utils/TypeInfo.cs index 3a1fd0f6ad..3cc2418511 100644 --- a/Stack/Opc.Ua.Core/Types/Utils/TypeInfo.cs +++ b/Stack/Opc.Ua.Core/Types/Utils/TypeInfo.cs @@ -11,14 +11,14 @@ */ using System; -using System.Xml; using System.Reflection; +using System.Xml; namespace Opc.Ua { - /// - /// The set of built-in data types for UA type descriptions. - /// + /// + /// The set of built-in data types for UA type descriptions. + /// /// /// An enumeration that lists all of the built-in data types for OPC UA Type Descriptions. /// @@ -174,7 +174,7 @@ namespace Opc.Ua /// Enumeration = 29 } - + /// /// Stores information about a type. /// @@ -195,7 +195,7 @@ namespace Opc.Ua /// /// Type of the built in. /// The value rank. - public TypeInfo( BuiltInType builtInType, int valueRank) + public TypeInfo(BuiltInType builtInType, int valueRank) { m_builtInType = builtInType; m_valueRank = valueRank; @@ -525,28 +525,19 @@ namespace Opc.Ua /// A constant representing an unknown type. /// /// The constant representing an unknown type. - public static TypeInfo Unknown - { - get { return s_Unknown; } - } + public static TypeInfo Unknown => s_Unknown; /// /// The built-in type. /// /// The type of the type represented by this instance. - public BuiltInType BuiltInType - { - get { return m_builtInType; } - } + public BuiltInType BuiltInType => m_builtInType; /// /// The value rank. /// /// The value rank of the type represented by this instance. - public int ValueRank - { - get { return m_valueRank; } - } + public int ValueRank => m_valueRank; /// /// Returns the type info if the value is an instance of the data type with the specified value rank. @@ -561,11 +552,11 @@ namespace Opc.Ua /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")] public static TypeInfo IsInstanceOfDataType( - object value, - NodeId expectedDataTypeId, - int expectedValueRank, - NamespaceTable namespaceUris, - ITypeTable typeTree) + object value, + NodeId expectedDataTypeId, + int expectedValueRank, + NamespaceTable namespaceUris, + ITypeTable typeTree) { BuiltInType expectedType = BuiltInType.Null; @@ -584,15 +575,15 @@ namespace Opc.Ua // check if the type supports nulls. switch (expectedType) - { - case BuiltInType.String: - case BuiltInType.ByteString: - case BuiltInType.XmlElement: - case BuiltInType.NodeId: - case BuiltInType.ExpandedNodeId: - case BuiltInType.LocalizedText: - case BuiltInType.QualifiedName: - case BuiltInType.DataValue: + { + case BuiltInType.String: + case BuiltInType.ByteString: + case BuiltInType.XmlElement: + case BuiltInType.NodeId: + case BuiltInType.ExpandedNodeId: + case BuiltInType.LocalizedText: + case BuiltInType.QualifiedName: + case BuiltInType.DataValue: case BuiltInType.Variant: case BuiltInType.ExtensionObject: { @@ -603,21 +594,7 @@ namespace Opc.Ua // nulls not allowed. return null; } - - // A ByteString is equivalent to an Array of Bytes. - if (typeInfo.BuiltInType == BuiltInType.ByteString && typeInfo.ValueRank == ValueRanks.Scalar) - { - if (expectedValueRank == ValueRanks.OneOrMoreDimensions || expectedValueRank == ValueRanks.OneDimension) - { - if (typeTree.IsTypeOf(expectedDataTypeId, DataTypes.Byte)) - { - return typeInfo; - } - return null; - } - } - // A ByteString is equivalent to an Array of Bytes. if (typeInfo.BuiltInType == BuiltInType.ByteString && typeInfo.ValueRank == ValueRanks.Scalar) { @@ -648,22 +625,22 @@ namespace Opc.Ua case DataTypes.Number: { switch (actualType) - { - case BuiltInType.SByte: - case BuiltInType.Int16: - case BuiltInType.Int32: - case BuiltInType.Int64: - case BuiltInType.Byte: - case BuiltInType.UInt16: - case BuiltInType.UInt32: - case BuiltInType.UInt64: - case BuiltInType.Double: - case BuiltInType.Float: + { + case BuiltInType.SByte: + case BuiltInType.Int16: + case BuiltInType.Int32: + case BuiltInType.Int64: + case BuiltInType.Byte: + case BuiltInType.UInt16: + case BuiltInType.UInt32: + case BuiltInType.UInt64: + case BuiltInType.Double: + case BuiltInType.Float: { return typeInfo; } - case BuiltInType.Variant: + case BuiltInType.Variant: { if (typeInfo.ValueRank == ValueRanks.Scalar) { @@ -685,16 +662,16 @@ namespace Opc.Ua case DataTypes.Integer: { switch (actualType) - { - case BuiltInType.SByte: - case BuiltInType.Int16: - case BuiltInType.Int32: - case BuiltInType.Int64: + { + case BuiltInType.SByte: + case BuiltInType.Int16: + case BuiltInType.Int32: + case BuiltInType.Int64: { return typeInfo; } - case BuiltInType.Variant: + case BuiltInType.Variant: { if (typeInfo.ValueRank == ValueRanks.Scalar) { @@ -716,16 +693,16 @@ namespace Opc.Ua case DataTypes.UInteger: { switch (actualType) - { - case BuiltInType.Byte: - case BuiltInType.UInt16: - case BuiltInType.UInt32: - case BuiltInType.UInt64: + { + case BuiltInType.Byte: + case BuiltInType.UInt16: + case BuiltInType.UInt32: + case BuiltInType.UInt64: { return typeInfo; } - case BuiltInType.Variant: + case BuiltInType.Variant: { if (typeInfo.ValueRank == ValueRanks.Scalar) { @@ -743,7 +720,7 @@ namespace Opc.Ua break; } - + case DataTypes.Enumeration: { if (typeInfo.BuiltInType == BuiltInType.Int32) @@ -775,7 +752,7 @@ namespace Opc.Ua } } } - + // check simple types. if (typeInfo.BuiltInType != BuiltInType.ExtensionObject && typeInfo.BuiltInType != BuiltInType.Variant) { @@ -783,7 +760,7 @@ namespace Opc.Ua { return typeInfo; } - + // check for enumerations. if (typeInfo.BuiltInType == BuiltInType.Int32) { @@ -810,7 +787,7 @@ namespace Opc.Ua if (typeInfo.BuiltInType == BuiltInType.ExtensionObject) { expectedType = GetBuiltInType(expectedDataTypeId, typeTree); - + if (expectedType == BuiltInType.Variant) { return typeInfo; @@ -832,68 +809,80 @@ namespace Opc.Ua return null; } - - // check every element in the array. - Array array = value as Array; - - BuiltInType actualElementType = GetBuiltInType(array.GetType().GetElementType().Name); - BuiltInType expectedElementType = TypeInfo.GetBuiltInType(expectedDataTypeId, typeTree); - // system type of array matches the expected type - nothing more to do. - if (actualElementType != BuiltInType.ExtensionObject && actualElementType == expectedElementType) + // check every element in the array or matrix. + Array array = value as Array; + if (array == null) { + Matrix matrix = value as Matrix; + if (matrix != null) + { + array = matrix.Elements; + } + } + + if (array != null) + { + BuiltInType expectedElementType = TypeInfo.GetBuiltInType(expectedDataTypeId, typeTree); + BuiltInType actualElementType = GetBuiltInType(array.GetType().GetElementType().Name); + // system type of array matches the expected type - nothing more to do. + if (actualElementType != BuiltInType.ExtensionObject && actualElementType == expectedElementType) + { + return typeInfo; + } + + // check for variant arrays. + if (expectedElementType == BuiltInType.Variant) + { + return typeInfo; + } + + // have to do it the hard way and check each element. + int[] dimensions = new int[array.Rank]; + + for (int ii = 0; ii < dimensions.Length; ii++) + { + dimensions[ii] = array.GetLength(ii); + } + + int[] indexes = new int[dimensions.Length]; + + for (int ii = 0; ii < array.Length; ii++) + { + int divisor = array.Length; + + for (int jj = 0; jj < indexes.Length; jj++) + { + divisor /= dimensions[jj]; + indexes[jj] = (ii / divisor) % dimensions[jj]; + } + + object element = array.GetValue(indexes); + + if (actualElementType == BuiltInType.Variant) + { + element = ((Variant)element).Value; + } + + TypeInfo elementInfo = TypeInfo.IsInstanceOfDataType( + element, + expectedDataTypeId, + ValueRanks.Scalar, + namespaceUris, + typeTree); + + // give up at the first invalid element. + if (elementInfo == null) + { + return null; + } + } + + // all elements valid. return typeInfo; } - // check for variant arrays. - if (expectedElementType == BuiltInType.Variant) - { - return typeInfo; - } - - // have to do it the hard way and check each element. - int[] dimensions = new int[array.Rank]; - - for (int ii = 0; ii < dimensions.Length; ii++) - { - dimensions[ii] = array.GetLength(ii); - } - - int[] indexes = new int[dimensions.Length]; - - for (int ii = 0; ii < array.Length; ii++) - { - int divisor = array.Length; - - for (int jj = 0; jj < indexes.Length; jj++) - { - divisor /= dimensions[jj]; - indexes[jj] = (ii/divisor)%dimensions[jj]; - } - - object element = array.GetValue(indexes); - - if (actualElementType == BuiltInType.Variant) - { - element = ((Variant)element).Value; - } - - TypeInfo elementInfo = TypeInfo.IsInstanceOfDataType( - element, - expectedDataTypeId, - ValueRanks.Scalar, - namespaceUris, - typeTree); - - // give up at the first invalid element. - if (elementInfo == null) - { - return null; - } - } - - // all elements valid. - return typeInfo; + return null; } /// @@ -945,35 +934,35 @@ namespace Opc.Ua { switch (builtInType) { - case BuiltInType.Boolean: return typeof(bool); - case BuiltInType.SByte: return typeof(sbyte); - case BuiltInType.Byte: return typeof(byte); - case BuiltInType.Int16: return typeof(short); - case BuiltInType.UInt16: return typeof(ushort); - case BuiltInType.Int32: return typeof(int); - case BuiltInType.UInt32: return typeof(uint); - case BuiltInType.Int64: return typeof(long); - case BuiltInType.UInt64: return typeof(ulong); - case BuiltInType.Float: return typeof(float); - case BuiltInType.Double: return typeof(double); - case BuiltInType.String: return typeof(string); - case BuiltInType.DateTime: return typeof(DateTime); - case BuiltInType.Guid: return typeof(Uuid); - case BuiltInType.ByteString: return typeof(byte[]); - case BuiltInType.XmlElement: return typeof(XmlElement); - case BuiltInType.NodeId: return typeof(NodeId); - case BuiltInType.ExpandedNodeId: return typeof(ExpandedNodeId); - case BuiltInType.LocalizedText: return typeof(LocalizedText); - case BuiltInType.QualifiedName: return typeof(QualifiedName); - case BuiltInType.StatusCode: return typeof(StatusCode); - case BuiltInType.DiagnosticInfo: return typeof(DiagnosticInfo); - case BuiltInType.DataValue: return typeof(DataValue); - case BuiltInType.Variant: return typeof(Variant); - case BuiltInType.ExtensionObject: return typeof(ExtensionObject); - case BuiltInType.Enumeration: return typeof(int); - case BuiltInType.Number: return typeof(Variant); - case BuiltInType.Integer: return typeof(Variant); - case BuiltInType.UInteger: return typeof(Variant); + case BuiltInType.Boolean: return typeof(bool); + case BuiltInType.SByte: return typeof(sbyte); + case BuiltInType.Byte: return typeof(byte); + case BuiltInType.Int16: return typeof(short); + case BuiltInType.UInt16: return typeof(ushort); + case BuiltInType.Int32: return typeof(int); + case BuiltInType.UInt32: return typeof(uint); + case BuiltInType.Int64: return typeof(long); + case BuiltInType.UInt64: return typeof(ulong); + case BuiltInType.Float: return typeof(float); + case BuiltInType.Double: return typeof(double); + case BuiltInType.String: return typeof(string); + case BuiltInType.DateTime: return typeof(DateTime); + case BuiltInType.Guid: return typeof(Uuid); + case BuiltInType.ByteString: return typeof(byte[]); + case BuiltInType.XmlElement: return typeof(XmlElement); + case BuiltInType.NodeId: return typeof(NodeId); + case BuiltInType.ExpandedNodeId: return typeof(ExpandedNodeId); + case BuiltInType.LocalizedText: return typeof(LocalizedText); + case BuiltInType.QualifiedName: return typeof(QualifiedName); + case BuiltInType.StatusCode: return typeof(StatusCode); + case BuiltInType.DiagnosticInfo: return typeof(DiagnosticInfo); + case BuiltInType.DataValue: return typeof(DataValue); + case BuiltInType.Variant: return typeof(Variant); + case BuiltInType.ExtensionObject: return typeof(ExtensionObject); + case BuiltInType.Enumeration: return typeof(int); + case BuiltInType.Number: return typeof(Variant); + case BuiltInType.Integer: return typeof(Variant); + case BuiltInType.UInteger: return typeof(Variant); } } @@ -981,71 +970,71 @@ namespace Opc.Ua { switch (builtInType) { - case BuiltInType.Boolean: return typeof(bool[]); - case BuiltInType.SByte: return typeof(sbyte[]); - case BuiltInType.Byte: return typeof(byte[]); - case BuiltInType.Int16: return typeof(short[]); - case BuiltInType.UInt16: return typeof(ushort[]); - case BuiltInType.Int32: return typeof(int[]); - case BuiltInType.UInt32: return typeof(uint[]); - case BuiltInType.Int64: return typeof(long[]); - case BuiltInType.UInt64: return typeof(ulong[]); - case BuiltInType.Float: return typeof(float[]); - case BuiltInType.Double: return typeof(double[]); - case BuiltInType.String: return typeof(string[]); - case BuiltInType.DateTime: return typeof(DateTime[]); - case BuiltInType.Guid: return typeof(Uuid[]); - case BuiltInType.ByteString: return typeof(byte[][]); - case BuiltInType.XmlElement: return typeof(XmlElement[]); - case BuiltInType.NodeId: return typeof(NodeId[]); - case BuiltInType.ExpandedNodeId: return typeof(ExpandedNodeId[]); - case BuiltInType.LocalizedText: return typeof(LocalizedText[]); - case BuiltInType.QualifiedName: return typeof(QualifiedName[]); - case BuiltInType.StatusCode: return typeof(StatusCode[]); - case BuiltInType.DiagnosticInfo: return typeof(DiagnosticInfo[]); - case BuiltInType.DataValue: return typeof(DataValue[]); - case BuiltInType.Variant: return typeof(Variant[]); - case BuiltInType.ExtensionObject: return typeof(ExtensionObject[]); - case BuiltInType.Enumeration: return typeof(int[]); - case BuiltInType.Number: return typeof(Variant[]); - case BuiltInType.Integer: return typeof(Variant[]); - case BuiltInType.UInteger: return typeof(Variant[]); + case BuiltInType.Boolean: return typeof(bool[]); + case BuiltInType.SByte: return typeof(sbyte[]); + case BuiltInType.Byte: return typeof(byte[]); + case BuiltInType.Int16: return typeof(short[]); + case BuiltInType.UInt16: return typeof(ushort[]); + case BuiltInType.Int32: return typeof(int[]); + case BuiltInType.UInt32: return typeof(uint[]); + case BuiltInType.Int64: return typeof(long[]); + case BuiltInType.UInt64: return typeof(ulong[]); + case BuiltInType.Float: return typeof(float[]); + case BuiltInType.Double: return typeof(double[]); + case BuiltInType.String: return typeof(string[]); + case BuiltInType.DateTime: return typeof(DateTime[]); + case BuiltInType.Guid: return typeof(Uuid[]); + case BuiltInType.ByteString: return typeof(byte[][]); + case BuiltInType.XmlElement: return typeof(XmlElement[]); + case BuiltInType.NodeId: return typeof(NodeId[]); + case BuiltInType.ExpandedNodeId: return typeof(ExpandedNodeId[]); + case BuiltInType.LocalizedText: return typeof(LocalizedText[]); + case BuiltInType.QualifiedName: return typeof(QualifiedName[]); + case BuiltInType.StatusCode: return typeof(StatusCode[]); + case BuiltInType.DiagnosticInfo: return typeof(DiagnosticInfo[]); + case BuiltInType.DataValue: return typeof(DataValue[]); + case BuiltInType.Variant: return typeof(Variant[]); + case BuiltInType.ExtensionObject: return typeof(ExtensionObject[]); + case BuiltInType.Enumeration: return typeof(int[]); + case BuiltInType.Number: return typeof(Variant[]); + case BuiltInType.Integer: return typeof(Variant[]); + case BuiltInType.UInteger: return typeof(Variant[]); } } - + else if (valueRank == ValueRanks.TwoDimensions) { switch (builtInType) { - case BuiltInType.Boolean: return typeof(bool[,]); - case BuiltInType.SByte: return typeof(sbyte[,]); - case BuiltInType.Byte: return typeof(byte[,]); - case BuiltInType.Int16: return typeof(short[,]); - case BuiltInType.UInt16: return typeof(ushort[,]); - case BuiltInType.Int32: return typeof(int[,]); - case BuiltInType.UInt32: return typeof(uint[,]); - case BuiltInType.Int64: return typeof(long[,]); - case BuiltInType.UInt64: return typeof(ulong[,]); - case BuiltInType.Float: return typeof(float[,]); - case BuiltInType.Double: return typeof(double[,]); - case BuiltInType.String: return typeof(string[,]); - case BuiltInType.DateTime: return typeof(DateTime[,]); - case BuiltInType.Guid: return typeof(Uuid[,]); - case BuiltInType.ByteString: return typeof(byte[,][]); - case BuiltInType.XmlElement: return typeof(XmlElement[,]); - case BuiltInType.NodeId: return typeof(NodeId[,]); - case BuiltInType.ExpandedNodeId: return typeof(ExpandedNodeId[,]); - case BuiltInType.LocalizedText: return typeof(LocalizedText[,]); - case BuiltInType.QualifiedName: return typeof(QualifiedName[,]); - case BuiltInType.StatusCode: return typeof(StatusCode[,]); - case BuiltInType.DiagnosticInfo: return typeof(DiagnosticInfo[,]); - case BuiltInType.DataValue: return typeof(DataValue[,]); - case BuiltInType.Variant: return typeof(Variant[,]); - case BuiltInType.ExtensionObject: return typeof(ExtensionObject[,]); - case BuiltInType.Enumeration: return typeof(int[,]); - case BuiltInType.Number: return typeof(Variant[,]); - case BuiltInType.Integer: return typeof(Variant[,]); - case BuiltInType.UInteger: return typeof(Variant[,]); + case BuiltInType.Boolean: return typeof(bool[,]); + case BuiltInType.SByte: return typeof(sbyte[,]); + case BuiltInType.Byte: return typeof(byte[,]); + case BuiltInType.Int16: return typeof(short[,]); + case BuiltInType.UInt16: return typeof(ushort[,]); + case BuiltInType.Int32: return typeof(int[,]); + case BuiltInType.UInt32: return typeof(uint[,]); + case BuiltInType.Int64: return typeof(long[,]); + case BuiltInType.UInt64: return typeof(ulong[,]); + case BuiltInType.Float: return typeof(float[,]); + case BuiltInType.Double: return typeof(double[,]); + case BuiltInType.String: return typeof(string[,]); + case BuiltInType.DateTime: return typeof(DateTime[,]); + case BuiltInType.Guid: return typeof(Uuid[,]); + case BuiltInType.ByteString: return typeof(byte[,][]); + case BuiltInType.XmlElement: return typeof(XmlElement[,]); + case BuiltInType.NodeId: return typeof(NodeId[,]); + case BuiltInType.ExpandedNodeId: return typeof(ExpandedNodeId[,]); + case BuiltInType.LocalizedText: return typeof(LocalizedText[,]); + case BuiltInType.QualifiedName: return typeof(QualifiedName[,]); + case BuiltInType.StatusCode: return typeof(StatusCode[,]); + case BuiltInType.DiagnosticInfo: return typeof(DiagnosticInfo[,]); + case BuiltInType.DataValue: return typeof(DataValue[,]); + case BuiltInType.Variant: return typeof(Variant[,]); + case BuiltInType.ExtensionObject: return typeof(ExtensionObject[,]); + case BuiltInType.Enumeration: return typeof(int[,]); + case BuiltInType.Number: return typeof(Variant[,]); + case BuiltInType.Integer: return typeof(Variant[,]); + case BuiltInType.UInteger: return typeof(Variant[,]); } } @@ -1100,7 +1089,7 @@ namespace Opc.Ua // parse array types. string dimensions = null; - if (name[name.Length-1] == ']') + if (name[name.Length - 1] == ']') { int index = name.IndexOf('['); @@ -1115,7 +1104,7 @@ namespace Opc.Ua if (dimensions == null) { BuiltInType builtInType = GetBuiltInType(name); - + if (builtInType != BuiltInType.Null) { return new TypeInfo(builtInType, ValueRanks.Scalar); @@ -1130,12 +1119,12 @@ namespace Opc.Ua if (name.EndsWith("Collection", StringComparison.Ordinal)) { builtInType = GetBuiltInType(name.Substring(0, name.Length - "Collection".Length)); - + if (builtInType != BuiltInType.Null) { return new TypeInfo(builtInType, ValueRanks.OneDimension); } - + // check for encodeable object. if (systemType.GetTypeInfo().BaseType.GetTypeInfo().IsGenericType) { @@ -1144,7 +1133,7 @@ namespace Opc.Ua return TypeInfo.Unknown; } - + // check for generic type. if (systemType.GetTypeInfo().IsGenericType) { @@ -1168,9 +1157,9 @@ namespace Opc.Ua { return new TypeInfo(BuiltInType.ExtensionObject, ValueRanks.Scalar); } - + return TypeInfo.Unknown; - } + } // handle one dimensional array. if (dimensions.Length == 2) @@ -1181,11 +1170,11 @@ namespace Opc.Ua { return new TypeInfo(BuiltInType.ByteString, ValueRanks.Scalar); } - + if (builtInType != BuiltInType.Null) { return new TypeInfo(builtInType, ValueRanks.OneDimension); - } + } // check for encodeable object. if (typeof(IEncodeable).GetTypeInfo().IsAssignableFrom(systemType.GetElementType().GetTypeInfo()) || name == "IEncodeable") @@ -1198,8 +1187,8 @@ namespace Opc.Ua // count the number of dimensions (syntax is [,] - commas+1 is the number of dimensions). int count = 1; - - for (int ii = 1; ii < dimensions.Length-1; ii++) + + for (int ii = 1; ii < dimensions.Length - 1; ii++) { if (dimensions[ii] == ',') { @@ -1208,7 +1197,7 @@ namespace Opc.Ua } // handle simple multi-dimensional array (enclosing [] + number of commas) - if (count+1 == dimensions.Length) + if (count + 1 == dimensions.Length) { BuiltInType builtInType = GetBuiltInType(name); @@ -1216,7 +1205,7 @@ namespace Opc.Ua { return new TypeInfo(builtInType, count); } - + // check for encodeable object. if (typeof(IEncodeable).GetTypeInfo().IsAssignableFrom(systemType.GetTypeInfo()) || name == "IEncodeable") { @@ -1230,7 +1219,7 @@ namespace Opc.Ua if (dimensions[1] == ']') { // syntax of type is [][,,,] - adding three checks for the middle '][' - if (name == "Byte" && count+3 == dimensions.Length) + if (name == "Byte" && count + 3 == dimensions.Length) { return new TypeInfo(BuiltInType.ByteString, count); } @@ -1260,8 +1249,8 @@ namespace Opc.Ua case BuiltInType.UInt64: { return (ulong)0; } case BuiltInType.Float: { return (float)0; } case BuiltInType.Double: { return (double)0; } - case BuiltInType.String: { return null; } - case BuiltInType.DateTime: { return DateTime.MinValue; } + case BuiltInType.String: { return null; } + case BuiltInType.DateTime: { return DateTime.MinValue; } case BuiltInType.Guid: { return Uuid.Empty; } case BuiltInType.ByteString: { return null; } case BuiltInType.XmlElement: { return null; } @@ -1301,7 +1290,7 @@ namespace Opc.Ua /// A default value. public static object GetDefaultValue(NodeId dataType, int valueRank, ITypeTable typeTree) { - if ( valueRank != ValueRanks.Scalar ) + if (valueRank != ValueRanks.Scalar) { return null; } @@ -1317,7 +1306,7 @@ namespace Opc.Ua { return GetDefaultValue((BuiltInType)(int)id); } - + switch (id) { case DataTypes.Duration: { return (double)0; } @@ -1333,14 +1322,14 @@ namespace Opc.Ua case DataTypes.Enumeration: { return (int)0; } } } - + builtInType = GetBuiltInType(dataType, typeTree); if (builtInType != BuiltInType.Null) { return GetDefaultValue(builtInType); } - + return null; } @@ -1357,7 +1346,7 @@ namespace Opc.Ua { throw new ArgumentOutOfRangeException("Array dimensions must be specifed."); } - + int length = dimensions[0]; // create one dimensional array. @@ -1377,11 +1366,11 @@ namespace Opc.Ua case BuiltInType.UInt64: { return new ulong[length]; } case BuiltInType.Float: { return new float[length]; } case BuiltInType.Double: { return new double[length]; } - case BuiltInType.String: { return new string[length]; } - case BuiltInType.DateTime: { return new DateTime[length]; } + case BuiltInType.String: { return new string[length]; } + case BuiltInType.DateTime: { return new DateTime[length]; } case BuiltInType.Guid: { return new Uuid[length]; } - case BuiltInType.ByteString: { return new byte[length][]; } - case BuiltInType.XmlElement: { return new XmlElement[length]; } + case BuiltInType.ByteString: { return new byte[length][]; } + case BuiltInType.XmlElement: { return new XmlElement[length]; } case BuiltInType.StatusCode: { return new StatusCode[length]; } case BuiltInType.NodeId: { return new NodeId[length]; } case BuiltInType.ExpandedNodeId: { return new ExpandedNodeId[length]; } @@ -1396,8 +1385,8 @@ namespace Opc.Ua case BuiltInType.Integer: { return new Variant[length]; } case BuiltInType.UInteger: { return new Variant[length]; } } - } - + } + // create higher dimension arrays. else { @@ -1415,11 +1404,11 @@ namespace Opc.Ua case BuiltInType.UInt64: { return Array.CreateInstance(typeof(ulong), dimensions); } case BuiltInType.Float: { return Array.CreateInstance(typeof(float), dimensions); } case BuiltInType.Double: { return Array.CreateInstance(typeof(double), dimensions); } - case BuiltInType.String: { return Array.CreateInstance(typeof(string), dimensions); } - case BuiltInType.DateTime: { return Array.CreateInstance(typeof(DateTime), dimensions); } + case BuiltInType.String: { return Array.CreateInstance(typeof(string), dimensions); } + case BuiltInType.DateTime: { return Array.CreateInstance(typeof(DateTime), dimensions); } case BuiltInType.Guid: { return Array.CreateInstance(typeof(Uuid), dimensions); } - case BuiltInType.ByteString: { return Array.CreateInstance(typeof(byte[]), dimensions); } - case BuiltInType.XmlElement: { return Array.CreateInstance(typeof(XmlElement), dimensions); } + case BuiltInType.ByteString: { return Array.CreateInstance(typeof(byte[]), dimensions); } + case BuiltInType.XmlElement: { return Array.CreateInstance(typeof(XmlElement), dimensions); } case BuiltInType.StatusCode: { return Array.CreateInstance(typeof(StatusCode), dimensions); } case BuiltInType.NodeId: { return Array.CreateInstance(typeof(NodeId), dimensions); } case BuiltInType.ExpandedNodeId: { return Array.CreateInstance(typeof(ExpandedNodeId), dimensions); } @@ -1449,7 +1438,7 @@ namespace Opc.Ua /// if imposible to cast. public static object Cast(object source, BuiltInType targetType) { - return Cast(source, TypeInfo.Construct(source), targetType); + return Cast(source, TypeInfo.Construct(source), targetType); } /// @@ -1489,32 +1478,32 @@ namespace Opc.Ua switch (targetType) { - case BuiltInType.Boolean: return Cast(source, sourceType, ToBoolean); - case BuiltInType.SByte: return Cast(source, sourceType, ToSByte); - case BuiltInType.Byte: return Cast(source, sourceType, ToByte); - case BuiltInType.Int16: return Cast(source, sourceType, ToInt16); - case BuiltInType.UInt16: return Cast(source, sourceType, ToUInt16); - case BuiltInType.Int32: return Cast(source, sourceType, ToInt32); - case BuiltInType.UInt32: return Cast(source, sourceType, ToUInt32); - case BuiltInType.Int64: return Cast(source, sourceType, ToInt64); - case BuiltInType.UInt64: return Cast(source, sourceType, ToUInt64); - case BuiltInType.Float: return Cast(source, sourceType, ToFloat); - case BuiltInType.Double: return Cast(source, sourceType, ToDouble); - case BuiltInType.String: return Cast(source, sourceType, ToString); - case BuiltInType.DateTime: return Cast(source, sourceType, ToDateTime); - case BuiltInType.Guid: return Cast(source, sourceType, ToGuid); - case BuiltInType.ByteString: return Cast(source, sourceType, ToByteString); - case BuiltInType.NodeId: return Cast(source, sourceType, ToNodeId); + case BuiltInType.Boolean: return Cast(source, sourceType, ToBoolean); + case BuiltInType.SByte: return Cast(source, sourceType, ToSByte); + case BuiltInType.Byte: return Cast(source, sourceType, ToByte); + case BuiltInType.Int16: return Cast(source, sourceType, ToInt16); + case BuiltInType.UInt16: return Cast(source, sourceType, ToUInt16); + case BuiltInType.Int32: return Cast(source, sourceType, ToInt32); + case BuiltInType.UInt32: return Cast(source, sourceType, ToUInt32); + case BuiltInType.Int64: return Cast(source, sourceType, ToInt64); + case BuiltInType.UInt64: return Cast(source, sourceType, ToUInt64); + case BuiltInType.Float: return Cast(source, sourceType, ToFloat); + case BuiltInType.Double: return Cast(source, sourceType, ToDouble); + case BuiltInType.String: return Cast(source, sourceType, ToString); + case BuiltInType.DateTime: return Cast(source, sourceType, ToDateTime); + case BuiltInType.Guid: return Cast(source, sourceType, ToGuid); + case BuiltInType.ByteString: return Cast(source, sourceType, ToByteString); + case BuiltInType.NodeId: return Cast(source, sourceType, ToNodeId); case BuiltInType.ExpandedNodeId: return Cast(source, sourceType, ToExpandedNodeId); - case BuiltInType.StatusCode: return Cast(source, sourceType, ToStatusCode); - case BuiltInType.QualifiedName: return Cast(source, sourceType, ToQualifiedName); - case BuiltInType.LocalizedText: return Cast(source, sourceType, ToLocalizedText); - case BuiltInType.Variant: return Cast(source, sourceType, ToVariant); - case BuiltInType.Number: return Cast(source, sourceType, ToDouble); - case BuiltInType.Integer: return Cast(source, sourceType, ToInt64); - case BuiltInType.UInteger: return Cast(source, sourceType, ToUInt64); - case BuiltInType.Enumeration: return Cast(source, sourceType, ToInt32); - case BuiltInType.XmlElement: return Cast(source, sourceType, ToXmlElement); + case BuiltInType.StatusCode: return Cast(source, sourceType, ToStatusCode); + case BuiltInType.QualifiedName: return Cast(source, sourceType, ToQualifiedName); + case BuiltInType.LocalizedText: return Cast(source, sourceType, ToLocalizedText); + case BuiltInType.Variant: return Cast(source, sourceType, ToVariant); + case BuiltInType.Number: return Cast(source, sourceType, ToDouble); + case BuiltInType.Integer: return Cast(source, sourceType, ToInt64); + case BuiltInType.UInteger: return Cast(source, sourceType, ToUInt64); + case BuiltInType.Enumeration: return Cast(source, sourceType, ToInt32); + case BuiltInType.XmlElement: return Cast(source, sourceType, ToXmlElement); } throw new InvalidCastException(); @@ -1579,7 +1568,7 @@ namespace Opc.Ua for (int jj = 0; jj < indexes.Length; jj++) { divisor /= dimensions[jj]; - indexes[jj] = (ii/divisor)%dimensions[jj]; + indexes[jj] = (ii / divisor) % dimensions[jj]; } object element = src.GetValue(indexes); @@ -1600,7 +1589,7 @@ namespace Opc.Ua { element = new Variant(element); } - + dst.SetValue(element, indexes); } } @@ -1620,7 +1609,7 @@ namespace Opc.Ua { return null; } - + int[] dimensions = new int[srcArray.Rank]; for (int ii = 0; ii < dimensions.Length; ii++) @@ -1643,7 +1632,7 @@ namespace Opc.Ua /// The converted public delegate object CastArrayElementHandler(object source, BuiltInType srcType, BuiltInType dstType); #endregion - + #region Private Methods /// /// Maps the type name to a built-in type. @@ -1653,34 +1642,34 @@ namespace Opc.Ua { switch (typeName) { - case "Boolean": return BuiltInType.Boolean; - case "SByte": return BuiltInType.SByte; - case "Byte": return BuiltInType.Byte; - case "Int16": return BuiltInType.Int16; - case "UInt16": return BuiltInType.UInt16; - case "Int32": return BuiltInType.Int32; - case "UInt32": return BuiltInType.UInt32; - case "Int64": return BuiltInType.Int64; - case "UInt64": return BuiltInType.UInt64; - case "Float": return BuiltInType.Float; - case "Single": return BuiltInType.Float; - case "Double": return BuiltInType.Double; - case "String": return BuiltInType.String; - case "DateTime": return BuiltInType.DateTime; - case "Guid": return BuiltInType.Guid; - case "Uuid": return BuiltInType.Guid; - case "ByteString": return BuiltInType.ByteString; - case "XmlElement": return BuiltInType.XmlElement; - case "NodeId": return BuiltInType.NodeId; - case "ExpandedNodeId": return BuiltInType.ExpandedNodeId; - case "LocalizedText": return BuiltInType.LocalizedText; - case "QualifiedName": return BuiltInType.QualifiedName; - case "StatusCode": return BuiltInType.StatusCode; - case "DiagnosticInfo": return BuiltInType.DiagnosticInfo; - case "DataValue": return BuiltInType.DataValue; - case "Variant": return BuiltInType.Variant; + case "Boolean": return BuiltInType.Boolean; + case "SByte": return BuiltInType.SByte; + case "Byte": return BuiltInType.Byte; + case "Int16": return BuiltInType.Int16; + case "UInt16": return BuiltInType.UInt16; + case "Int32": return BuiltInType.Int32; + case "UInt32": return BuiltInType.UInt32; + case "Int64": return BuiltInType.Int64; + case "UInt64": return BuiltInType.UInt64; + case "Float": return BuiltInType.Float; + case "Single": return BuiltInType.Float; + case "Double": return BuiltInType.Double; + case "String": return BuiltInType.String; + case "DateTime": return BuiltInType.DateTime; + case "Guid": return BuiltInType.Guid; + case "Uuid": return BuiltInType.Guid; + case "ByteString": return BuiltInType.ByteString; + case "XmlElement": return BuiltInType.XmlElement; + case "NodeId": return BuiltInType.NodeId; + case "ExpandedNodeId": return BuiltInType.ExpandedNodeId; + case "LocalizedText": return BuiltInType.LocalizedText; + case "QualifiedName": return BuiltInType.QualifiedName; + case "StatusCode": return BuiltInType.StatusCode; + case "DiagnosticInfo": return BuiltInType.DiagnosticInfo; + case "DataValue": return BuiltInType.DataValue; + case "Variant": return BuiltInType.Variant; case "ExtensionObject": return BuiltInType.ExtensionObject; - case "Object": return BuiltInType.Variant; + case "Object": return BuiltInType.Variant; } return BuiltInType.Null; @@ -1690,32 +1679,32 @@ namespace Opc.Ua /// Converts a value to a Boolean /// private static bool ToBoolean(object value, TypeInfo sourceType) - { + { // handle for supported conversions. switch (sourceType.BuiltInType) { case BuiltInType.Boolean: { - return (bool)value; + return (bool)value; } - - case BuiltInType.SByte: return Convert.ToBoolean((sbyte)value); - case BuiltInType.Byte: return Convert.ToBoolean((byte)value); - case BuiltInType.Int16: return Convert.ToBoolean((short)value); - case BuiltInType.UInt16: return Convert.ToBoolean((ushort)value); - case BuiltInType.Int32: return Convert.ToBoolean((int)value); - case BuiltInType.UInt32: return Convert.ToBoolean((uint)value); - case BuiltInType.Int64: return Convert.ToBoolean((long)value); - case BuiltInType.UInt64: return Convert.ToBoolean((ulong)value); - case BuiltInType.Float: return Convert.ToBoolean((float)value); - case BuiltInType.Double: return Convert.ToBoolean((double)value); + + case BuiltInType.SByte: return Convert.ToBoolean((sbyte)value); + case BuiltInType.Byte: return Convert.ToBoolean((byte)value); + case BuiltInType.Int16: return Convert.ToBoolean((short)value); + case BuiltInType.UInt16: return Convert.ToBoolean((ushort)value); + case BuiltInType.Int32: return Convert.ToBoolean((int)value); + case BuiltInType.UInt32: return Convert.ToBoolean((uint)value); + case BuiltInType.Int64: return Convert.ToBoolean((long)value); + case BuiltInType.UInt64: return Convert.ToBoolean((ulong)value); + case BuiltInType.Float: return Convert.ToBoolean((float)value); + case BuiltInType.Double: return Convert.ToBoolean((double)value); case BuiltInType.String: { - return XmlConvert.ToBoolean((string)value); + return XmlConvert.ToBoolean((string)value); } } - + // conversion not supported. throw new InvalidCastException(); } @@ -1724,32 +1713,32 @@ namespace Opc.Ua /// Converts a value to a SByte /// private static sbyte ToSByte(object value, TypeInfo sourceType) - { + { // handle for supported conversions. switch (sourceType.BuiltInType) { case BuiltInType.SByte: { - return (sbyte)value; + return (sbyte)value; } - + case BuiltInType.Boolean: return Convert.ToSByte((bool)value); - case BuiltInType.Byte: return Convert.ToSByte((byte)value); - case BuiltInType.Int16: return Convert.ToSByte((short)value); - case BuiltInType.UInt16: return Convert.ToSByte((ushort)value); - case BuiltInType.Int32: return Convert.ToSByte((int)value); - case BuiltInType.UInt32: return Convert.ToSByte((uint)value); - case BuiltInType.Int64: return Convert.ToSByte((long)value); - case BuiltInType.UInt64: return Convert.ToSByte((ulong)value); - case BuiltInType.Float: return Convert.ToSByte((float)value); - case BuiltInType.Double: return Convert.ToSByte((double)value); + case BuiltInType.Byte: return Convert.ToSByte((byte)value); + case BuiltInType.Int16: return Convert.ToSByte((short)value); + case BuiltInType.UInt16: return Convert.ToSByte((ushort)value); + case BuiltInType.Int32: return Convert.ToSByte((int)value); + case BuiltInType.UInt32: return Convert.ToSByte((uint)value); + case BuiltInType.Int64: return Convert.ToSByte((long)value); + case BuiltInType.UInt64: return Convert.ToSByte((ulong)value); + case BuiltInType.Float: return Convert.ToSByte((float)value); + case BuiltInType.Double: return Convert.ToSByte((double)value); case BuiltInType.String: { - return XmlConvert.ToSByte((string)value); + return XmlConvert.ToSByte((string)value); } } - + // conversion not supported. throw new InvalidCastException(); } @@ -1758,66 +1747,66 @@ namespace Opc.Ua /// Converts a value to a Byte /// private static byte ToByte(object value, TypeInfo sourceType) - { + { // handle for supported conversions. switch (sourceType.BuiltInType) { case BuiltInType.Byte: { - return (byte)value; + return (byte)value; } - + case BuiltInType.Boolean: return Convert.ToByte((bool)value); - case BuiltInType.SByte: return Convert.ToByte((sbyte)value); - case BuiltInType.Int16: return Convert.ToByte((short)value); - case BuiltInType.UInt16: return Convert.ToByte((ushort)value); - case BuiltInType.Int32: return Convert.ToByte((int)value); - case BuiltInType.UInt32: return Convert.ToByte((uint)value); - case BuiltInType.Int64: return Convert.ToByte((long)value); - case BuiltInType.UInt64: return Convert.ToByte((ulong)value); - case BuiltInType.Float: return Convert.ToByte((float)value); - case BuiltInType.Double: return Convert.ToByte((double)value); + case BuiltInType.SByte: return Convert.ToByte((sbyte)value); + case BuiltInType.Int16: return Convert.ToByte((short)value); + case BuiltInType.UInt16: return Convert.ToByte((ushort)value); + case BuiltInType.Int32: return Convert.ToByte((int)value); + case BuiltInType.UInt32: return Convert.ToByte((uint)value); + case BuiltInType.Int64: return Convert.ToByte((long)value); + case BuiltInType.UInt64: return Convert.ToByte((ulong)value); + case BuiltInType.Float: return Convert.ToByte((float)value); + case BuiltInType.Double: return Convert.ToByte((double)value); case BuiltInType.String: { - return XmlConvert.ToByte((string)value); + return XmlConvert.ToByte((string)value); } } - + // conversion not supported. throw new InvalidCastException(); } - + /// /// Converts a value to a Int16 /// private static short ToInt16(object value, TypeInfo sourceType) - { + { // handle for supported conversions. switch (sourceType.BuiltInType) { case BuiltInType.Int16: { - return (short)value; + return (short)value; } - + case BuiltInType.Boolean: return Convert.ToInt16((bool)value); - case BuiltInType.SByte: return Convert.ToInt16((sbyte)value); - case BuiltInType.Byte: return Convert.ToInt16((byte)value); - case BuiltInType.UInt16: return Convert.ToInt16((ushort)value); - case BuiltInType.Int32: return Convert.ToInt16((int)value); - case BuiltInType.UInt32: return Convert.ToInt16((uint)value); - case BuiltInType.Int64: return Convert.ToInt16((long)value); - case BuiltInType.UInt64: return Convert.ToInt16((ulong)value); - case BuiltInType.Float: return Convert.ToInt16((float)value); - case BuiltInType.Double: return Convert.ToInt16((double)value); + case BuiltInType.SByte: return Convert.ToInt16((sbyte)value); + case BuiltInType.Byte: return Convert.ToInt16((byte)value); + case BuiltInType.UInt16: return Convert.ToInt16((ushort)value); + case BuiltInType.Int32: return Convert.ToInt16((int)value); + case BuiltInType.UInt32: return Convert.ToInt16((uint)value); + case BuiltInType.Int64: return Convert.ToInt16((long)value); + case BuiltInType.UInt64: return Convert.ToInt16((ulong)value); + case BuiltInType.Float: return Convert.ToInt16((float)value); + case BuiltInType.Double: return Convert.ToInt16((double)value); case BuiltInType.String: { - return XmlConvert.ToInt16((string)value); + return XmlConvert.ToInt16((string)value); } } - + // conversion not supported. throw new InvalidCastException(); } @@ -1826,77 +1815,77 @@ namespace Opc.Ua /// Converts a value to a UInt16 /// private static ushort ToUInt16(object value, TypeInfo sourceType) - { + { // handle for supported conversions. switch (sourceType.BuiltInType) { case BuiltInType.UInt16: { - return (ushort)value; + return (ushort)value; } - + case BuiltInType.Boolean: return Convert.ToUInt16((bool)value); - case BuiltInType.SByte: return Convert.ToUInt16((sbyte)value); - case BuiltInType.Byte: return Convert.ToUInt16((byte)value); - case BuiltInType.Int16: return Convert.ToUInt16((short)value); - case BuiltInType.Int32: return Convert.ToUInt16((int)value); - case BuiltInType.UInt32: return Convert.ToUInt16((uint)value); - case BuiltInType.Int64: return Convert.ToUInt16((long)value); - case BuiltInType.UInt64: return Convert.ToUInt16((ulong)value); - case BuiltInType.Float: return Convert.ToUInt16((float)value); - case BuiltInType.Double: return Convert.ToUInt16((double)value); + case BuiltInType.SByte: return Convert.ToUInt16((sbyte)value); + case BuiltInType.Byte: return Convert.ToUInt16((byte)value); + case BuiltInType.Int16: return Convert.ToUInt16((short)value); + case BuiltInType.Int32: return Convert.ToUInt16((int)value); + case BuiltInType.UInt32: return Convert.ToUInt16((uint)value); + case BuiltInType.Int64: return Convert.ToUInt16((long)value); + case BuiltInType.UInt64: return Convert.ToUInt16((ulong)value); + case BuiltInType.Float: return Convert.ToUInt16((float)value); + case BuiltInType.Double: return Convert.ToUInt16((double)value); case BuiltInType.String: { - return XmlConvert.ToUInt16((string)value); + return XmlConvert.ToUInt16((string)value); } case BuiltInType.StatusCode: { StatusCode code = (StatusCode)value; - return (ushort)(code.CodeBits>>16); + return (ushort)(code.CodeBits >> 16); } } - + // conversion not supported. throw new InvalidCastException(); } - + /// /// Converts a value to a Int32 /// private static int ToInt32(object value, TypeInfo sourceType) - { + { // handle for supported conversions. switch (sourceType.BuiltInType) { case BuiltInType.Int32: { - return (int)value; + return (int)value; } - + case BuiltInType.Boolean: return Convert.ToInt32((bool)value); - case BuiltInType.SByte: return Convert.ToInt32((sbyte)value); - case BuiltInType.Byte: return Convert.ToInt32((byte)value); - case BuiltInType.Int16: return Convert.ToInt32((short)value); - case BuiltInType.UInt16: return Convert.ToInt32((ushort)value); - case BuiltInType.UInt32: return Convert.ToInt32((uint)value); - case BuiltInType.Int64: return Convert.ToInt32((long)value); - case BuiltInType.UInt64: return Convert.ToInt32((ulong)value); - case BuiltInType.Float: return Convert.ToInt32((float)value); - case BuiltInType.Double: return Convert.ToInt32((double)value); + case BuiltInType.SByte: return Convert.ToInt32((sbyte)value); + case BuiltInType.Byte: return Convert.ToInt32((byte)value); + case BuiltInType.Int16: return Convert.ToInt32((short)value); + case BuiltInType.UInt16: return Convert.ToInt32((ushort)value); + case BuiltInType.UInt32: return Convert.ToInt32((uint)value); + case BuiltInType.Int64: return Convert.ToInt32((long)value); + case BuiltInType.UInt64: return Convert.ToInt32((ulong)value); + case BuiltInType.Float: return Convert.ToInt32((float)value); + case BuiltInType.Double: return Convert.ToInt32((double)value); case BuiltInType.String: { - return XmlConvert.ToInt32((string)value); + return XmlConvert.ToInt32((string)value); } case BuiltInType.StatusCode: { - return Convert.ToInt32(((StatusCode)value).Code); + return Convert.ToInt32(((StatusCode)value).Code); } } - + // conversion not supported. throw new InvalidCastException(); } @@ -1905,192 +1894,192 @@ namespace Opc.Ua /// Converts a value to a UInt32 /// private static uint ToUInt32(object value, TypeInfo sourceType) - { + { // handle for supported conversions. switch (sourceType.BuiltInType) { case BuiltInType.UInt32: { - return (uint)value; + return (uint)value; } - + case BuiltInType.Boolean: return Convert.ToUInt32((bool)value); - case BuiltInType.SByte: return Convert.ToUInt32((sbyte)value); - case BuiltInType.Byte: return Convert.ToUInt32((byte)value); - case BuiltInType.Int16: return Convert.ToUInt32((short)value); - case BuiltInType.UInt16: return Convert.ToUInt32((ushort)value); - case BuiltInType.Int32: return Convert.ToUInt32((int)value); - case BuiltInType.Int64: return Convert.ToUInt32((long)value); - case BuiltInType.UInt64: return Convert.ToUInt32((ulong)value); - case BuiltInType.Float: return Convert.ToUInt32((float)value); - case BuiltInType.Double: return Convert.ToUInt32((double)value); + case BuiltInType.SByte: return Convert.ToUInt32((sbyte)value); + case BuiltInType.Byte: return Convert.ToUInt32((byte)value); + case BuiltInType.Int16: return Convert.ToUInt32((short)value); + case BuiltInType.UInt16: return Convert.ToUInt32((ushort)value); + case BuiltInType.Int32: return Convert.ToUInt32((int)value); + case BuiltInType.Int64: return Convert.ToUInt32((long)value); + case BuiltInType.UInt64: return Convert.ToUInt32((ulong)value); + case BuiltInType.Float: return Convert.ToUInt32((float)value); + case BuiltInType.Double: return Convert.ToUInt32((double)value); case BuiltInType.String: { - return XmlConvert.ToUInt32((string)value); + return XmlConvert.ToUInt32((string)value); } case BuiltInType.StatusCode: { - return Convert.ToUInt32(((StatusCode)value).Code); + return Convert.ToUInt32(((StatusCode)value).Code); } } - + // conversion not supported. throw new InvalidCastException(); } - + /// /// Converts a value to a Int64 /// private static long ToInt64(object value, TypeInfo sourceType) - { + { // handle for supported conversions. switch (sourceType.BuiltInType) { case BuiltInType.Int64: { - return (long)value; + return (long)value; } - + case BuiltInType.Boolean: return Convert.ToInt64((bool)value); - case BuiltInType.SByte: return Convert.ToInt64((sbyte)value); - case BuiltInType.Byte: return Convert.ToInt64((byte)value); - case BuiltInType.Int16: return Convert.ToInt64((short)value); - case BuiltInType.UInt16: return Convert.ToInt64((ushort)value); - case BuiltInType.Int32: return Convert.ToInt64((int)value); - case BuiltInType.UInt32: return Convert.ToInt64((uint)value); - case BuiltInType.UInt64: return Convert.ToInt64((ulong)value); - case BuiltInType.Float: return Convert.ToInt64((float)value); - case BuiltInType.Double: return Convert.ToInt64((double)value); + case BuiltInType.SByte: return Convert.ToInt64((sbyte)value); + case BuiltInType.Byte: return Convert.ToInt64((byte)value); + case BuiltInType.Int16: return Convert.ToInt64((short)value); + case BuiltInType.UInt16: return Convert.ToInt64((ushort)value); + case BuiltInType.Int32: return Convert.ToInt64((int)value); + case BuiltInType.UInt32: return Convert.ToInt64((uint)value); + case BuiltInType.UInt64: return Convert.ToInt64((ulong)value); + case BuiltInType.Float: return Convert.ToInt64((float)value); + case BuiltInType.Double: return Convert.ToInt64((double)value); case BuiltInType.String: { - return XmlConvert.ToInt64((string)value); + return XmlConvert.ToInt64((string)value); } case BuiltInType.StatusCode: { - return Convert.ToInt64(((StatusCode)value).Code); + return Convert.ToInt64(((StatusCode)value).Code); } } - + // conversion not supported. throw new InvalidCastException(); - } - + } + /// /// Converts a value to a UInt64 /// private static ulong ToUInt64(object value, TypeInfo sourceType) - { + { // handle for supported conversions. switch (sourceType.BuiltInType) { case BuiltInType.UInt64: { - return (ulong)value; + return (ulong)value; } - + case BuiltInType.Boolean: return Convert.ToUInt64((bool)value); - case BuiltInType.SByte: return Convert.ToUInt64((sbyte)value); - case BuiltInType.Byte: return Convert.ToUInt64((byte)value); - case BuiltInType.Int16: return Convert.ToUInt64((short)value); - case BuiltInType.UInt16: return Convert.ToUInt64((ushort)value); - case BuiltInType.Int32: return Convert.ToUInt64((int)value); - case BuiltInType.UInt32: return Convert.ToUInt64((uint)value); - case BuiltInType.Int64: return Convert.ToUInt64((long)value); - case BuiltInType.Float: return Convert.ToUInt64((float)value); - case BuiltInType.Double: return Convert.ToUInt64((double)value); + case BuiltInType.SByte: return Convert.ToUInt64((sbyte)value); + case BuiltInType.Byte: return Convert.ToUInt64((byte)value); + case BuiltInType.Int16: return Convert.ToUInt64((short)value); + case BuiltInType.UInt16: return Convert.ToUInt64((ushort)value); + case BuiltInType.Int32: return Convert.ToUInt64((int)value); + case BuiltInType.UInt32: return Convert.ToUInt64((uint)value); + case BuiltInType.Int64: return Convert.ToUInt64((long)value); + case BuiltInType.Float: return Convert.ToUInt64((float)value); + case BuiltInType.Double: return Convert.ToUInt64((double)value); case BuiltInType.String: { - return XmlConvert.ToUInt64((string)value); + return XmlConvert.ToUInt64((string)value); } case BuiltInType.StatusCode: { - return Convert.ToUInt64(((StatusCode)value).Code); + return Convert.ToUInt64(((StatusCode)value).Code); } } - + // conversion not supported. throw new InvalidCastException(); - } + } /// /// Converts a value to a Float /// private static float ToFloat(object value, TypeInfo sourceType) - { + { // handle for supported conversions. switch (sourceType.BuiltInType) { case BuiltInType.Float: { - return (float)value; + return (float)value; } - + case BuiltInType.Boolean: return Convert.ToSingle((bool)value); - case BuiltInType.SByte: return Convert.ToSingle((sbyte)value); - case BuiltInType.Byte: return Convert.ToSingle((byte)value); - case BuiltInType.Int16: return Convert.ToSingle((short)value); - case BuiltInType.UInt16: return Convert.ToSingle((ushort)value); - case BuiltInType.Int32: return Convert.ToSingle((int)value); - case BuiltInType.UInt32: return Convert.ToSingle((uint)value); - case BuiltInType.Int64: return Convert.ToSingle((long)value); - case BuiltInType.UInt64: return Convert.ToSingle((ulong)value); - case BuiltInType.Double: return Convert.ToSingle((double)value); + case BuiltInType.SByte: return Convert.ToSingle((sbyte)value); + case BuiltInType.Byte: return Convert.ToSingle((byte)value); + case BuiltInType.Int16: return Convert.ToSingle((short)value); + case BuiltInType.UInt16: return Convert.ToSingle((ushort)value); + case BuiltInType.Int32: return Convert.ToSingle((int)value); + case BuiltInType.UInt32: return Convert.ToSingle((uint)value); + case BuiltInType.Int64: return Convert.ToSingle((long)value); + case BuiltInType.UInt64: return Convert.ToSingle((ulong)value); + case BuiltInType.Double: return Convert.ToSingle((double)value); case BuiltInType.String: { - return XmlConvert.ToSingle((string)value); + return XmlConvert.ToSingle((string)value); } } - + // conversion not supported. throw new InvalidCastException(); - } - + } + /// /// Converts a value to a Double /// private static double ToDouble(object value, TypeInfo sourceType) - { + { // handle for supported conversions. switch (sourceType.BuiltInType) { case BuiltInType.Double: { - return (double)value; + return (double)value; } - + case BuiltInType.Boolean: return Convert.ToDouble((bool)value); - case BuiltInType.SByte: return Convert.ToDouble((sbyte)value); - case BuiltInType.Byte: return Convert.ToDouble((byte)value); - case BuiltInType.Int16: return Convert.ToDouble((short)value); - case BuiltInType.UInt16: return Convert.ToDouble((ushort)value); - case BuiltInType.Int32: return Convert.ToDouble((int)value); - case BuiltInType.UInt32: return Convert.ToDouble((uint)value); - case BuiltInType.Int64: return Convert.ToDouble((long)value); - case BuiltInType.UInt64: return Convert.ToDouble((ulong)value); - case BuiltInType.Float: return Convert.ToDouble((float)value); + case BuiltInType.SByte: return Convert.ToDouble((sbyte)value); + case BuiltInType.Byte: return Convert.ToDouble((byte)value); + case BuiltInType.Int16: return Convert.ToDouble((short)value); + case BuiltInType.UInt16: return Convert.ToDouble((ushort)value); + case BuiltInType.Int32: return Convert.ToDouble((int)value); + case BuiltInType.UInt32: return Convert.ToDouble((uint)value); + case BuiltInType.Int64: return Convert.ToDouble((long)value); + case BuiltInType.UInt64: return Convert.ToDouble((ulong)value); + case BuiltInType.Float: return Convert.ToDouble((float)value); case BuiltInType.String: { - return XmlConvert.ToDouble((string)value); + return XmlConvert.ToDouble((string)value); } } - + // conversion not supported. throw new InvalidCastException(); - } + } /// /// Converts a value to a String /// private static string ToString(object value, TypeInfo sourceType) - { + { // handle for supported conversions. switch (sourceType.BuiltInType) { @@ -2106,82 +2095,82 @@ namespace Opc.Ua case BuiltInType.SByte: { - return XmlConvert.ToString((sbyte)value); + return XmlConvert.ToString((sbyte)value); } case BuiltInType.Byte: { - return XmlConvert.ToString((byte)value); + return XmlConvert.ToString((byte)value); } case BuiltInType.Int16: { - return XmlConvert.ToString((short)value); + return XmlConvert.ToString((short)value); } case BuiltInType.UInt16: { - return XmlConvert.ToString((ushort)value); + return XmlConvert.ToString((ushort)value); } case BuiltInType.Int32: { - return XmlConvert.ToString((int)value); + return XmlConvert.ToString((int)value); } case BuiltInType.UInt32: { - return XmlConvert.ToString((uint)value); + return XmlConvert.ToString((uint)value); } case BuiltInType.Int64: { - return XmlConvert.ToString((long)value); + return XmlConvert.ToString((long)value); } case BuiltInType.UInt64: { - return XmlConvert.ToString((ulong)value); + return XmlConvert.ToString((ulong)value); } case BuiltInType.Float: { - return XmlConvert.ToString((float)value); + return XmlConvert.ToString((float)value); } case BuiltInType.Double: { - return XmlConvert.ToString((double)value); + return XmlConvert.ToString((double)value); } case BuiltInType.DateTime: { - return XmlConvert.ToString((DateTime)value, XmlDateTimeSerializationMode.Unspecified); + return XmlConvert.ToString((DateTime)value, XmlDateTimeSerializationMode.Unspecified); } case BuiltInType.Guid: { - return ((Uuid)value).ToString(); + return ((Uuid)value).ToString(); } case BuiltInType.NodeId: { - return ((NodeId)value).ToString(); + return ((NodeId)value).ToString(); } case BuiltInType.ExpandedNodeId: { - return ((ExpandedNodeId)value).ToString(); + return ((ExpandedNodeId)value).ToString(); } case BuiltInType.LocalizedText: { - return ((LocalizedText)value).Text; + return ((LocalizedText)value).Text; } case BuiltInType.QualifiedName: { - return ((QualifiedName)value).ToString(); + return ((QualifiedName)value).ToString(); } case BuiltInType.XmlElement: @@ -2201,10 +2190,10 @@ namespace Opc.Ua case BuiltInType.Null: { - return null; + return null; } } - + // conversion not supported. throw new InvalidCastException(); } @@ -2213,21 +2202,21 @@ namespace Opc.Ua /// Converts a value to a DateTime /// private static DateTime ToDateTime(object value, TypeInfo sourceType) - { + { // handle for supported conversions. switch (sourceType.BuiltInType) { case BuiltInType.DateTime: { - return (DateTime)value; + return (DateTime)value; } case BuiltInType.String: { - return XmlConvert.ToDateTime((string)value, XmlDateTimeSerializationMode.Unspecified); + return XmlConvert.ToDateTime((string)value, XmlDateTimeSerializationMode.Unspecified); } } - + // conversion not supported. throw new InvalidCastException(); } @@ -2236,18 +2225,18 @@ namespace Opc.Ua /// Converts a value to a Guid /// private static Uuid ToGuid(object value, TypeInfo sourceType) - { + { // handle for supported conversions. switch (sourceType.BuiltInType) { case BuiltInType.String: { - return new Uuid((string)value); + return new Uuid((string)value); } case BuiltInType.ByteString: { - return new Uuid(new Guid((byte[])value)); + return new Uuid(new Guid((byte[])value)); } case BuiltInType.Guid: @@ -2259,10 +2248,10 @@ namespace Opc.Ua return new Uuid(guid.Value); } - return (Uuid)value; + return (Uuid)value; } } - + // conversion not supported. throw new InvalidCastException(); } @@ -2271,13 +2260,13 @@ namespace Opc.Ua /// Converts a value to a ByteString /// private static byte[] ToByteString(object value, TypeInfo sourceType) - { + { // handle for supported conversions. switch (sourceType.BuiltInType) { case BuiltInType.ByteString: { - return (byte[])value; + return (byte[])value; } case BuiltInType.String: @@ -2345,10 +2334,10 @@ namespace Opc.Ua case BuiltInType.Guid: { - return ((Guid)((Uuid)value)).ToByteArray(); + return ((Guid)((Uuid)value)).ToByteArray(); } } - + // conversion not supported. throw new InvalidCastException(); } @@ -2357,13 +2346,13 @@ namespace Opc.Ua /// Converts a value to a XmlElement /// private static XmlElement ToXmlElement(object value, TypeInfo sourceType) - { + { // handle for supported conversions. switch (sourceType.BuiltInType) { case BuiltInType.XmlElement: { - return (XmlElement)value; + return (XmlElement)value; } case BuiltInType.String: @@ -2373,7 +2362,7 @@ namespace Opc.Ua return document.DocumentElement; } } - + // conversion not supported. throw new InvalidCastException(); } @@ -2382,18 +2371,18 @@ namespace Opc.Ua /// Converts a value to a NodeId /// private static NodeId ToNodeId(object value, TypeInfo sourceType) - { + { // handle for supported conversions. switch (sourceType.BuiltInType) { case BuiltInType.NodeId: { - return (NodeId)value; + return (NodeId)value; } case BuiltInType.ExpandedNodeId: { - return (NodeId)(ExpandedNodeId)value; + return (NodeId)(ExpandedNodeId)value; } case BuiltInType.String: @@ -2401,7 +2390,7 @@ namespace Opc.Ua return NodeId.Parse((string)value); } } - + // conversion not supported. throw new InvalidCastException(); } @@ -2410,18 +2399,18 @@ namespace Opc.Ua /// Converts a value to a ExpandedNodeId /// private static ExpandedNodeId ToExpandedNodeId(object value, TypeInfo sourceType) - { + { // handle for supported conversions. switch (sourceType.BuiltInType) { case BuiltInType.ExpandedNodeId: { - return (ExpandedNodeId)value; + return (ExpandedNodeId)value; } case BuiltInType.NodeId: { - return (ExpandedNodeId)(NodeId)value; + return (ExpandedNodeId)(NodeId)value; } case BuiltInType.String: @@ -2429,7 +2418,7 @@ namespace Opc.Ua return ExpandedNodeId.Parse((string)value); } } - + // conversion not supported. throw new InvalidCastException(); } @@ -2438,35 +2427,35 @@ namespace Opc.Ua /// Converts a value to a StatusCode /// private static StatusCode ToStatusCode(object value, TypeInfo sourceType) - { + { // handle for supported conversions. switch (sourceType.BuiltInType) { case BuiltInType.StatusCode: { - return (StatusCode)value; + return (StatusCode)value; } case BuiltInType.UInt16: { uint code = Convert.ToUInt32((ushort)value); code <<= 16; - return (StatusCode)code; + return (StatusCode)code; } case BuiltInType.Int32: { - return (StatusCode)Convert.ToUInt32((int)value); - } + return (StatusCode)Convert.ToUInt32((int)value); + } case BuiltInType.UInt32: { - return (StatusCode)(uint)value; - } - + return (StatusCode)(uint)value; + } + case BuiltInType.Int64: { - return (StatusCode)Convert.ToUInt32((long)value); + return (StatusCode)Convert.ToUInt32((long)value); } case BuiltInType.UInt64: @@ -2482,7 +2471,7 @@ namespace Opc.Ua { return StatusCodes.Good; } - + text = text.Trim(); if (text.StartsWith("0x")) @@ -2493,22 +2482,22 @@ namespace Opc.Ua return (StatusCode)Convert.ToUInt32((string)value); } } - + // conversion not supported. throw new InvalidCastException(); } - + /// /// Converts a value to a QualifiedName /// private static QualifiedName ToQualifiedName(object value, TypeInfo sourceType) - { + { // handle for supported conversions. switch (sourceType.BuiltInType) { case BuiltInType.QualifiedName: { - return (QualifiedName)value; + return (QualifiedName)value; } case BuiltInType.String: @@ -2516,7 +2505,7 @@ namespace Opc.Ua return QualifiedName.Parse((string)value); } } - + // conversion not supported. throw new InvalidCastException(); } @@ -2525,13 +2514,13 @@ namespace Opc.Ua /// Converts a value to a LocalizedText /// private static LocalizedText ToLocalizedText(object value, TypeInfo sourceType) - { + { // handle for supported conversions. switch (sourceType.BuiltInType) { case BuiltInType.LocalizedText: { - return (LocalizedText)value; + return (LocalizedText)value; } case BuiltInType.String: @@ -2543,20 +2532,20 @@ namespace Opc.Ua // conversion not supported. throw new InvalidCastException(); } - + /// /// Converts a value to a Variant /// private static Variant ToVariant(object value, TypeInfo sourceType) - { + { return new Variant(value); } - + /// /// Delegate for a function used to cast a value to the specified type. /// private delegate T CastDelegate(object value, TypeInfo sourceType); - + /// /// Casts a scalar or array value to the specified type. /// @@ -2578,7 +2567,7 @@ namespace Opc.Ua sourceType = TypeInfo.Construct(value); return handler(value, sourceType); } - + return handler(input, sourceType); } @@ -2609,7 +2598,7 @@ namespace Opc.Ua value = ((Variant)value).Value; elementType = TypeInfo.Construct(value); } - + copy[ii] = handler(value, elementType); } } @@ -2622,14 +2611,14 @@ namespace Opc.Ua int x = input.GetLength(0); int y = input.GetLength(1); - T[,] copy = new T[x,y]; + T[,] copy = new T[x, y]; for (int ii = 0; ii < x; ii++) { for (int jj = 0; jj < y; jj++) { object value = input.GetValue(ii, jj); - + if (value != null) { if (sourceType.BuiltInType == BuiltInType.Variant) @@ -2637,7 +2626,7 @@ namespace Opc.Ua value = ((Variant)value).Value; elementType = TypeInfo.Construct(value); } - + copy[ii, jj] = handler(value, elementType); } } @@ -2652,9 +2641,9 @@ namespace Opc.Ua { dimensions[ii] = input.GetLength(ii); } - + Array output = Array.CreateInstance(typeof(T), dimensions); - + int length = output.Length; int[] indexes = new int[dimensions.Length]; @@ -2665,11 +2654,11 @@ namespace Opc.Ua for (int jj = 0; jj < indexes.Length; jj++) { divisor /= dimensions[jj]; - indexes[jj] = (ii/divisor)%dimensions[jj]; + indexes[jj] = (ii / divisor) % dimensions[jj]; } - + object value = input.GetValue(indexes); - + if (value != null) { if (sourceType.BuiltInType == BuiltInType.Variant) @@ -2684,15 +2673,15 @@ namespace Opc.Ua return output; } -#endregion - -#region Private Fields + #endregion + + #region Private Fields private BuiltInType m_builtInType; private int m_valueRank; private static readonly TypeInfo s_Unknown = new TypeInfo(); -#endregion - -#region Scalars Class + #endregion + + #region Scalars Class /// /// Constants for scalar types. /// @@ -2824,9 +2813,9 @@ namespace Opc.Ua /// public static readonly TypeInfo DiagnosticInfo = new TypeInfo(BuiltInType.DiagnosticInfo, ValueRanks.Scalar); } -#endregion + #endregion -#region Arrays Class + #region Arrays Class /// /// Constants for one dimensional array types. /// @@ -2958,9 +2947,9 @@ namespace Opc.Ua /// public static readonly TypeInfo DiagnosticInfo = new TypeInfo(BuiltInType.DiagnosticInfo, ValueRanks.OneDimension); } -#endregion + #endregion -#region IFormattable Members + #region IFormattable Members /// /// Formats the type information as a string. /// @@ -2993,9 +2982,9 @@ namespace Opc.Ua return buffer.ToString(); } - + throw new FormatException(Utils.Format("Invalid format string: '{0}'.", format)); } -#endregion + #endregion } }