• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #region Copyright notice and license
2 
3 // Copyright 2015 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 
17 #endregion
18 
19 using System;
20 using System.Threading.Tasks;
21 using Grpc.Core.Internal;
22 
23 namespace Grpc.Core
24 {
25     /// <summary>
26     /// Helper methods for generated clients to make RPC calls.
27     /// Most users will use this class only indirectly and will be
28     /// making calls using client object generated from protocol
29     /// buffer definition files.
30     /// </summary>
31     public static class Calls
32     {
33         /// <summary>
34         /// Invokes a simple remote call in a blocking fashion.
35         /// </summary>
36         /// <returns>The response.</returns>
37         /// <param name="call">The call definition.</param>
38         /// <param name="req">Request message.</param>
39         /// <typeparam name="TRequest">Type of request message.</typeparam>
40         /// <typeparam name="TResponse">The of response message.</typeparam>
41         public static TResponse BlockingUnaryCall<TRequest, TResponse>(CallInvocationDetails<TRequest, TResponse> call, TRequest req)
42             where TRequest : class
43             where TResponse : class
44         {
45             var asyncCall = new AsyncCall<TRequest, TResponse>(call);
46             return asyncCall.UnaryCall(req);
47         }
48 
49         /// <summary>
50         /// Invokes a simple remote call asynchronously.
51         /// </summary>
52         /// <returns>An awaitable call object providing access to the response.</returns>
53         /// <param name="call">The call definition.</param>
54         /// <param name="req">Request message.</param>
55         /// <typeparam name="TRequest">Type of request message.</typeparam>
56         /// <typeparam name="TResponse">The of response message.</typeparam>
57         public static AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(CallInvocationDetails<TRequest, TResponse> call, TRequest req)
58             where TRequest : class
59             where TResponse : class
60         {
61             var asyncCall = new AsyncCall<TRequest, TResponse>(call);
62             var asyncResult = asyncCall.UnaryCallAsync(req);
63             return new AsyncUnaryCall<TResponse>(asyncResult,
64                 Callbacks<TRequest, TResponse>.GetHeaders, Callbacks<TRequest, TResponse>.GetStatus,
65                 Callbacks<TRequest, TResponse>.GetTrailers, Callbacks<TRequest, TResponse>.Cancel,
66                 asyncCall);
67         }
68 
69         /// <summary>
70         /// Invokes a server streaming call asynchronously.
71         /// In server streaming scenario, client sends on request and server responds with a stream of responses.
72         /// </summary>
73         /// <returns>A call object providing access to the asynchronous response stream.</returns>
74         /// <param name="call">The call definition.</param>
75         /// <param name="req">Request message.</param>
76         /// <typeparam name="TRequest">Type of request message.</typeparam>
77         /// <typeparam name="TResponse">The of response messages.</typeparam>
78         public static AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TRequest, TResponse>(CallInvocationDetails<TRequest, TResponse> call, TRequest req)
79             where TRequest : class
80             where TResponse : class
81         {
82             var asyncCall = new AsyncCall<TRequest, TResponse>(call);
asyncCall.StartServerStreamingCall(req)83             asyncCall.StartServerStreamingCall(req);
84             var responseStream = new ClientResponseStream<TRequest, TResponse>(asyncCall);
85             return new AsyncServerStreamingCall<TResponse>(responseStream,
86                 Callbacks<TRequest, TResponse>.GetHeaders, Callbacks<TRequest, TResponse>.GetStatus,
87                 Callbacks<TRequest, TResponse>.GetTrailers, Callbacks<TRequest, TResponse>.Cancel,
88                 asyncCall);
89         }
90 
91         /// <summary>
92         /// Invokes a client streaming call asynchronously.
93         /// In client streaming scenario, client sends a stream of requests and server responds with a single response.
94         /// </summary>
95         /// <param name="call">The call definition.</param>
96         /// <returns>An awaitable call object providing access to the response.</returns>
97         /// <typeparam name="TRequest">Type of request messages.</typeparam>
98         /// <typeparam name="TResponse">The of response message.</typeparam>
99         public static AsyncClientStreamingCall<TRequest, TResponse> AsyncClientStreamingCall<TRequest, TResponse>(CallInvocationDetails<TRequest, TResponse> call)
100             where TRequest : class
101             where TResponse : class
102         {
103             var asyncCall = new AsyncCall<TRequest, TResponse>(call);
104             var resultTask = asyncCall.ClientStreamingCallAsync();
105             var requestStream = new ClientRequestStream<TRequest, TResponse>(asyncCall);
106             return new AsyncClientStreamingCall<TRequest, TResponse>(requestStream, resultTask,
107                 Callbacks<TRequest, TResponse>.GetHeaders, Callbacks<TRequest, TResponse>.GetStatus,
108                 Callbacks<TRequest, TResponse>.GetTrailers, Callbacks<TRequest, TResponse>.Cancel,
109                 asyncCall);
110         }
111 
112         /// <summary>
113         /// Invokes a duplex streaming call asynchronously.
114         /// In duplex streaming scenario, client sends a stream of requests and server responds with a stream of responses.
115         /// The response stream is completely independent and both side can be sending messages at the same time.
116         /// </summary>
117         /// <returns>A call object providing access to the asynchronous request and response streams.</returns>
118         /// <param name="call">The call definition.</param>
119         /// <typeparam name="TRequest">Type of request messages.</typeparam>
120         /// <typeparam name="TResponse">Type of responsemessages.</typeparam>
121         public static AsyncDuplexStreamingCall<TRequest, TResponse> AsyncDuplexStreamingCall<TRequest, TResponse>(CallInvocationDetails<TRequest, TResponse> call)
122             where TRequest : class
123             where TResponse : class
124         {
125             var asyncCall = new AsyncCall<TRequest, TResponse>(call);
asyncCall.StartDuplexStreamingCall()126             asyncCall.StartDuplexStreamingCall();
127             var requestStream = new ClientRequestStream<TRequest, TResponse>(asyncCall);
128             var responseStream = new ClientResponseStream<TRequest, TResponse>(asyncCall);
129             return new AsyncDuplexStreamingCall<TRequest, TResponse>(requestStream, responseStream,
130                 Callbacks<TRequest, TResponse>.GetHeaders, Callbacks<TRequest, TResponse>.GetStatus,
131                 Callbacks<TRequest, TResponse>.GetTrailers, Callbacks<TRequest, TResponse>.Cancel,
132                 asyncCall);
133         }
134 
135         private static class Callbacks<TRequest, TResponse>
136         {
137             internal static readonly Func<object, Task<Metadata>> GetHeaders = state => ((AsyncCall<TRequest, TResponse>)state).ResponseHeadersAsync;
138             internal static readonly Func<object, Status> GetStatus = state => ((AsyncCall<TRequest, TResponse>)state).GetStatus();
139             internal static readonly Func<object, Metadata> GetTrailers = state => ((AsyncCall<TRequest, TResponse>)state).GetTrailers();
140             internal static readonly Action<object> Cancel = state => ((AsyncCall<TRequest, TResponse>)state).Cancel();
141         }
142     }
143 }
144