internal static async Task <Tuple <Argument[], Argument[]> > GetMethodArgumentsFromNodeId(this UaSession session, NodeId nodeId)
        {
            var inputArguments   = new Argument[0];
            var outputArguments  = new Argument[0];
            var translateRequest = new TranslateBrowsePathsToNodeIdsRequest {
                BrowsePaths = { new BrowsePath {
                                    StartingNode = nodeId, RelativePath = new RelativePath(ReferenceTypeIds.HasProperty, "InputArguments")
                                }, new BrowsePath{
                                    StartingNode = nodeId, RelativePath = new RelativePath(ReferenceTypeIds.HasProperty, "OutputArguments")
                                } }
            };
            var translateResponse = await session.TranslateBrowsePathsToNodeIdsAsync(translateRequest);

            if (StatusCode.IsGood(translateResponse.Results[0].StatusCode) && translateResponse.Results[0].Targets.Count > 0)
            {
                var argNodeId   = ExpandedNodeId.ToNodeId(translateResponse.Results[0].Targets[0].TargetId, session.NamespaceUris);
                var readRequest = new ReadRequest {
                    NodesToRead = { new ReadValueId {
                                        NodeId = argNodeId, AttributeId = Attributes.Value
                                    } }
                };
                var readResponse = await session.ReadAsync(readRequest);

                if (StatusCode.IsGood(readResponse.Results[0].StatusCode))
                {
                    var value = readResponse.Results[0].GetValue <ExtensionObject[]>(null);
                    if (value != null)
                    {
                        inputArguments = (Argument[])ExtensionObject.ToArray(value, typeof(Argument));
                    }
                }
            }
            if (StatusCode.IsGood(translateResponse.Results[1].StatusCode) && translateResponse.Results[1].Targets.Count > 0)
            {
                var argNodeId   = ExpandedNodeId.ToNodeId(translateResponse.Results[1].Targets[0].TargetId, session.NamespaceUris);
                var readRequest = new ReadRequest {
                    NodesToRead = { new ReadValueId {
                                        NodeId = argNodeId, AttributeId = Attributes.Value
                                    } }
                };
                var readResponse = await session.ReadAsync(readRequest);

                if (StatusCode.IsGood(readResponse.Results[0].StatusCode))
                {
                    var value = readResponse.Results[0].GetValue <ExtensionObject[]>(null);
                    if (value != null)
                    {
                        outputArguments = (Argument[])ExtensionObject.ToArray(value, typeof(Argument));
                    }
                }
            }
            return(Tuple.Create(inputArguments, outputArguments));
        }
        internal static async Task <Type> GetDataTypeFromNodeId(this UaSession session, NodeId nodeId)
        {
            var readRequest = new ReadRequest {
                NodesToRead = { new ReadValueId {
                                    NodeId = nodeId, AttributeId = Attributes.DataType
                                }, new ReadValueId{
                                    NodeId = nodeId, AttributeId = Attributes.ValueRank
                                } }
            };
            var readResponse = await session.ReadAsync(readRequest);

            var dataType  = readResponse.Results[0].GetValue(NodeId.Null);
            var valueRank = readResponse.Results[1].GetValue(-2);
            var type      = TypeInfo.GetSystemType(dataType, session.Factory);

            if (type != null)
            {
                if (valueRank > 0)
                {
                    return(type.MakeArrayType(valueRank));
                }
                return(type);
            }
            return(typeof(object));
        }