///<summary>Sends a "jms/stream-message"-encoded RPC request, ///and expects an RPC reply in the same format.</summary> ///<remarks> ///<para> /// The arguments passed in must be of types that are /// representable as JMS StreamMessage values, and so must the /// results returned from the service in its reply message. ///</para> ///<para> /// Calls OnTimedOut() and OnDisconnected() when a timeout or /// disconnection, respectively, is detected when waiting for /// our reply. ///</para> ///<para> /// Returns null if the request timed out or if we were /// disconnected before a reply arrived. ///</para> ///<para> /// The reply message, if any, is acknowledged to the AMQP /// server via Subscription.Ack(). ///</para> ///</remarks> ///<see cref="IStreamMessageBuilder"/> ///<see cref="IStreamMessageReader"/> public virtual object[] Call(params object[] args) { IStreamMessageBuilder builder = new StreamMessageBuilder(Model); builder.WriteObjects(args); IBasicProperties replyProperties; byte[] replyBody = Call((IBasicProperties)builder.GetContentHeader(), builder.GetContentBody(), out replyProperties); if (replyProperties == null) { return null; } if (replyProperties.ContentType != StreamMessageBuilder.MimeType) { throw new ProtocolViolationException (string.Format("Expected reply of MIME type {0}; got {1}", StreamMessageBuilder.MimeType, replyProperties.ContentType)); } IStreamMessageReader reader = new StreamMessageReader(replyProperties, replyBody); return reader.ReadObjects(); }
///<summary>Called by ProcessRequest(), this is the most ///general method that handles RPC-style requests.</summary> ///<remarks> ///<para> /// This method should map requestProperties and body to /// replyProperties and the returned byte array. ///</para> ///<para> /// The default implementation checks /// requestProperties.ContentType, and if it is /// "jms/stream-message" (i.e. the current value of /// StreamMessageBuilder.MimeType), parses it using /// StreamMessageReader and delegates to /// HandleStreamMessageCall before encoding and returning the /// reply. If the ContentType is any other value, the request /// is passed to HandleSimpleCall instead. ///</para> ///<para> /// The isRedelivered flag is true when the server knows for /// sure that it has tried to send this request previously /// (although not necessarily to this application). It is not /// a reliable indicator of previous receipt, however - the /// only claim it makes is that a delivery attempt was made, /// not that the attempt succeeded. Be careful if you choose /// to use the isRedelivered flag. ///</para> ///</remarks> public virtual byte[] HandleCall(bool isRedelivered, IBasicProperties requestProperties, byte[] body, out IBasicProperties replyProperties) { if (requestProperties.ContentType == StreamMessageBuilder.MimeType) { IStreamMessageReader r = new StreamMessageReader(requestProperties, body); IStreamMessageBuilder w = new StreamMessageBuilder(m_subscription.Model); HandleStreamMessageCall(w, isRedelivered, requestProperties, r.ReadObjects()); replyProperties = (IBasicProperties) w.GetContentHeader(); return w.GetContentBody(); } else { return HandleSimpleCall(isRedelivered, requestProperties, body, out replyProperties); } }