/// <summary>
        /// Gets the specified attribute values for the specified scanner.
        /// </summary>
        /// <param name="scannerService"></param>
        /// <param name="scannerId"></param>
        /// <param name="attributes"></param>
        /// <returns></returns>
        public static IObservable <IReadOnlyCollection <AttributeInfo> > GetAttributeValuesAsync(
            this ICoreScannerService scannerService,
            Int32 scannerId,
            params AttributeId[] attributes)
        {
            Contract.Requires(scannerService != null);
            Contract.Requires(scannerId > 0);
            Contract.Requires(attributes.Length > 0);

            XDocument inXml = new XDocument(
                new XElement("inArgs",
                             new XElement("scannerID", scannerId),
                             new XElement("cmdArgs",
                                          new XElement("arg-xml",
                                                       new XElement("attrib_list", attributes.Cast <Int32>().ToArray())))));
            IObservable <IReadOnlyCollection <AttributeInfo> > resultAsync = scannerService
                                                                             .WhenCommandResponded()
                                                                             .Do(e => e.Status.ThrowIfError())
                                                                             .SelectMany(e => e.OutXml
                                                                                         .ParseXmlDocument()
                                                                                         .Elements("outArgs"))
                                                                             .Where(outXml => outXml
                                                                                    .Elements("scannerID")
                                                                                    .All(e => e.Value.ToInt32().Equals(scannerId)))
                                                                             .SelectMany(outXml => outXml
                                                                                         .Elements("arg-xml")
                                                                                         .Elements("response"))
                                                                             .Where(response => response
                                                                                    .Elements("opcode")
                                                                                    .Select(e => (OperationCode)e.Value.ToInt32())
                                                                                    .All(opCode => opCode.Equals(OperationCode.GetAttribute)))
                                                                             .FirstAsync()
                                                                             .RunAsync(CancellationToken.None)
                                                                             .Select(outXml => outXml
                                                                                     .Elements("attrib_list")
                                                                                     .Elements("attribute")
                                                                                     .Select(e => AttributeInfo.Parse(e.ToString()))
                                                                                     .ToList()
                                                                                     .AsReadOnly());

            scannerService
            .ExecuteCommandAsync(OperationCode.GetAttribute, inXml.ToString());
            return(resultAsync);
        }
        /// <summary>
        /// Gets the next attribute value of the specified attribute for the specified scanner.
        /// </summary>
        /// <param name="scannerService"></param>
        /// <param name="scannerId"></param>
        /// <param name="attribute"></param>
        /// <returns></returns>
        /// <remarks>
        /// Can be used to create an asynchronous scanner attribute iterator.
        /// </remarks>
        public static IObservable <AttributeInfo> GetNextAttributeValueAsync(
            this ICoreScannerService scannerService,
            Int32 scannerId,
            AttributeId attributeId)
        {
            Contract.Requires(scannerService != null);
            Contract.Requires(scannerId > 0);

            XDocument inXml = new XDocument(
                new XElement("inArgs",
                             new XElement("scannerID", scannerId),
                             new XElement("cmdArgs",
                                          new XElement("arg-xml",
                                                       new XElement("attrib_list", (Int32)attributeId)))));
            IObservable <AttributeInfo> resultAsync = scannerService
                                                      .WhenCommandResponded()
                                                      .Do(e => e.Status.ThrowIfError())
                                                      .SelectMany(e => e.OutXml
                                                                  .ParseXmlDocument()
                                                                  .Elements("outArgs"))
                                                      .Where(outArgs => outArgs
                                                             .Elements("scannerID")
                                                             .All(e => e.Value.ToInt32().Equals(scannerId)))
                                                      .SelectMany(outArgs => outArgs
                                                                  .Elements("arg-xml")
                                                                  .Elements("response"))
                                                      .Where(response => response
                                                             .Elements("opcode")
                                                             .Select(opCode => (OperationCode)opCode.Value.ToInt32())
                                                             .All(opCode => opCode.Equals(OperationCode.GetNextAttribute)))
                                                      .FirstAsync()
                                                      .RunAsync(CancellationToken.None)
                                                      .SelectMany(response => response
                                                                  .Elements("attrib_list")
                                                                  .Elements("attribute")
                                                                  .Select(attribute => AttributeInfo.Parse(attribute.ToString())));

            scannerService
            .ExecuteCommandAsync(OperationCode.GetNextAttribute, inXml.ToString());
            return(resultAsync);
        }