From bdb1b4863bf0d03fb08f240677a7aa3726bb3f1c Mon Sep 17 00:00:00 2001
From: Jan Tattermusch <jtattermusch@google.com>
Date: Wed, 6 May 2015 14:46:25 -0700
Subject: [PATCH] add a generic constraint for TRequest and TResponse to
 require a class

---
 src/csharp/Grpc.Core/AsyncClientStreamingCall.cs |  4 +++-
 src/csharp/Grpc.Core/AsyncDuplexStreamingCall.cs |  4 +++-
 src/csharp/Grpc.Core/AsyncServerStreamingCall.cs |  3 ++-
 src/csharp/Grpc.Core/Call.cs                     |  2 ++
 src/csharp/Grpc.Core/Calls.cs                    | 10 ++++++++++
 src/csharp/Grpc.Core/IAsyncStreamReader.cs       |  3 ++-
 src/csharp/Grpc.Core/IAsyncStreamWriter.cs       |  1 +
 src/csharp/Grpc.Core/IClientStreamWriter.cs      |  1 +
 src/csharp/Grpc.Core/IServerStreamWriter.cs      |  1 +
 .../Grpc.Core/Internal/ClientRequestStream.cs    |  2 ++
 .../Grpc.Core/Internal/ClientResponseStream.cs   |  2 ++
 .../Grpc.Core/Internal/ServerCallHandler.cs      |  8 ++++++++
 src/csharp/Grpc.Core/Internal/ServerCalls.cs     |  8 ++++++++
 .../Grpc.Core/Internal/ServerRequestStream.cs    |  2 ++
 .../Grpc.Core/Internal/ServerResponseStream.cs   |  2 ++
 src/csharp/Grpc.Core/ServerMethods.cs            | 16 ++++++++++++----
 src/csharp/Grpc.Core/ServerServiceDefinition.cs  |  8 ++++++++
 src/csharp/Grpc.Core/Stub/AbstractStub.cs        |  2 ++
 18 files changed, 71 insertions(+), 8 deletions(-)

diff --git a/src/csharp/Grpc.Core/AsyncClientStreamingCall.cs b/src/csharp/Grpc.Core/AsyncClientStreamingCall.cs
index e81ce01ebb..b95776f66d 100644
--- a/src/csharp/Grpc.Core/AsyncClientStreamingCall.cs
+++ b/src/csharp/Grpc.Core/AsyncClientStreamingCall.cs
@@ -40,7 +40,9 @@ namespace Grpc.Core
     /// <summary>
     /// Return type for client streaming calls.
     /// </summary>
-    public struct AsyncClientStreamingCall<TRequest, TResponse>
+    public sealed class AsyncClientStreamingCall<TRequest, TResponse>
+        where TRequest : class
+        where TResponse : class
     {
         readonly IClientStreamWriter<TRequest> requestStream;
         readonly Task<TResponse> result;
diff --git a/src/csharp/Grpc.Core/AsyncDuplexStreamingCall.cs b/src/csharp/Grpc.Core/AsyncDuplexStreamingCall.cs
index 1cb30f4779..ee05437416 100644
--- a/src/csharp/Grpc.Core/AsyncDuplexStreamingCall.cs
+++ b/src/csharp/Grpc.Core/AsyncDuplexStreamingCall.cs
@@ -40,7 +40,9 @@ namespace Grpc.Core
     /// <summary>
     /// Return type for bidirectional streaming calls.
     /// </summary>
-    public struct AsyncDuplexStreamingCall<TRequest, TResponse>
+    public sealed class AsyncDuplexStreamingCall<TRequest, TResponse>
+        where TRequest : class
+        where TResponse : class
     {
         readonly IClientStreamWriter<TRequest> requestStream;
         readonly IAsyncStreamReader<TResponse> responseStream;
diff --git a/src/csharp/Grpc.Core/AsyncServerStreamingCall.cs b/src/csharp/Grpc.Core/AsyncServerStreamingCall.cs
index d614916fb7..73b9614985 100644
--- a/src/csharp/Grpc.Core/AsyncServerStreamingCall.cs
+++ b/src/csharp/Grpc.Core/AsyncServerStreamingCall.cs
@@ -40,7 +40,8 @@ namespace Grpc.Core
     /// <summary>
     /// Return type for server streaming calls.
     /// </summary>
-    public struct AsyncServerStreamingCall<TResponse>
+    public sealed class AsyncServerStreamingCall<TResponse>
+        where TResponse : class
     {
         readonly IAsyncStreamReader<TResponse> responseStream;
 
diff --git a/src/csharp/Grpc.Core/Call.cs b/src/csharp/Grpc.Core/Call.cs
index 070dfb569d..771cc083da 100644
--- a/src/csharp/Grpc.Core/Call.cs
+++ b/src/csharp/Grpc.Core/Call.cs
@@ -41,6 +41,8 @@ namespace Grpc.Core
     /// Abstraction of a call to be invoked on a client.
     /// </summary>
     public class Call<TRequest, TResponse>
+        where TRequest : class
+        where TResponse : class
     {
         readonly string name;
         readonly Marshaller<TRequest> requestMarshaller;
diff --git a/src/csharp/Grpc.Core/Calls.cs b/src/csharp/Grpc.Core/Calls.cs
index a8d2b9498e..ba42a2d4f8 100644
--- a/src/csharp/Grpc.Core/Calls.cs
+++ b/src/csharp/Grpc.Core/Calls.cs
@@ -44,6 +44,8 @@ namespace Grpc.Core
     public static class Calls
     {
         public static TResponse BlockingUnaryCall<TRequest, TResponse>(Call<TRequest, TResponse> call, TRequest req, CancellationToken token)
+            where TRequest : class
+            where TResponse : class
         {
             var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer);
             // TODO(jtattermusch): this gives a race that cancellation can be requested before the call even starts.
@@ -52,6 +54,8 @@ namespace Grpc.Core
         }
 
         public static async Task<TResponse> AsyncUnaryCall<TRequest, TResponse>(Call<TRequest, TResponse> call, TRequest req, CancellationToken token)
+            where TRequest : class
+            where TResponse : class
         {
             var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer);
             asyncCall.Initialize(call.Channel, GetCompletionQueue(), call.Name);
@@ -61,6 +65,8 @@ namespace Grpc.Core
         }
 
         public static AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TRequest, TResponse>(Call<TRequest, TResponse> call, TRequest req, CancellationToken token)
+            where TRequest : class
+            where TResponse : class
         {
             var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer);
             asyncCall.Initialize(call.Channel, GetCompletionQueue(), call.Name);
@@ -71,6 +77,8 @@ namespace Grpc.Core
         }
 
         public static AsyncClientStreamingCall<TRequest, TResponse> AsyncClientStreamingCall<TRequest, TResponse>(Call<TRequest, TResponse> call, CancellationToken token)
+            where TRequest : class
+            where TResponse : class
         {
             var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer);
             asyncCall.Initialize(call.Channel, GetCompletionQueue(), call.Name);
@@ -81,6 +89,8 @@ namespace Grpc.Core
         }
 
         public static AsyncDuplexStreamingCall<TRequest, TResponse> AsyncDuplexStreamingCall<TRequest, TResponse>(Call<TRequest, TResponse> call, CancellationToken token)
+            where TRequest : class
+            where TResponse : class
         {
             var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer);
             asyncCall.Initialize(call.Channel, GetCompletionQueue(), call.Name);
diff --git a/src/csharp/Grpc.Core/IAsyncStreamReader.cs b/src/csharp/Grpc.Core/IAsyncStreamReader.cs
index 61cf57f7e0..699741cd05 100644
--- a/src/csharp/Grpc.Core/IAsyncStreamReader.cs
+++ b/src/csharp/Grpc.Core/IAsyncStreamReader.cs
@@ -44,9 +44,10 @@ namespace Grpc.Core
     /// </summary>
     /// <typeparam name="T"></typeparam>
     public interface IAsyncStreamReader<T>
+        where T : class
     {
         /// <summary>
-        /// Reads a single message. Returns default(T) if the last message was already read.
+        /// Reads a single message. Returns null if the last message was already read.
         /// A following read can only be started when the previous one finishes.
         /// </summary>
         Task<T> ReadNext();
diff --git a/src/csharp/Grpc.Core/IAsyncStreamWriter.cs b/src/csharp/Grpc.Core/IAsyncStreamWriter.cs
index 724bae8f31..4bd8bfb8df 100644
--- a/src/csharp/Grpc.Core/IAsyncStreamWriter.cs
+++ b/src/csharp/Grpc.Core/IAsyncStreamWriter.cs
@@ -44,6 +44,7 @@ namespace Grpc.Core
     /// </summary>
     /// <typeparam name="T"></typeparam>
     public interface IAsyncStreamWriter<T>
+        where T : class
     {
         /// <summary>
         /// Writes a single message. Only one write can be pending at a time.
diff --git a/src/csharp/Grpc.Core/IClientStreamWriter.cs b/src/csharp/Grpc.Core/IClientStreamWriter.cs
index 6da42e9ccc..0847a928e6 100644
--- a/src/csharp/Grpc.Core/IClientStreamWriter.cs
+++ b/src/csharp/Grpc.Core/IClientStreamWriter.cs
@@ -44,6 +44,7 @@ namespace Grpc.Core
     /// </summary>
     /// <typeparam name="T"></typeparam>
     public interface IClientStreamWriter<T> : IAsyncStreamWriter<T>
+        where T : class
     {
         /// <summary>
         /// Closes the stream. Can only be called once there is no pending write. No writes should follow calling this.
diff --git a/src/csharp/Grpc.Core/IServerStreamWriter.cs b/src/csharp/Grpc.Core/IServerStreamWriter.cs
index e76397d8a0..199a585a3f 100644
--- a/src/csharp/Grpc.Core/IServerStreamWriter.cs
+++ b/src/csharp/Grpc.Core/IServerStreamWriter.cs
@@ -43,6 +43,7 @@ namespace Grpc.Core
     /// A writable stream of messages that is used in server-side handlers.
     /// </summary>
     public interface IServerStreamWriter<T> : IAsyncStreamWriter<T>
+        where T : class
     {
     }
 }
diff --git a/src/csharp/Grpc.Core/Internal/ClientRequestStream.cs b/src/csharp/Grpc.Core/Internal/ClientRequestStream.cs
index 6854922a6f..1697058732 100644
--- a/src/csharp/Grpc.Core/Internal/ClientRequestStream.cs
+++ b/src/csharp/Grpc.Core/Internal/ClientRequestStream.cs
@@ -38,6 +38,8 @@ namespace Grpc.Core.Internal
     /// Writes requests asynchronously to an underlying AsyncCall object.
     /// </summary>
     internal class ClientRequestStream<TRequest, TResponse> : IClientStreamWriter<TRequest>
+        where TRequest : class
+        where TResponse : class
     {
         readonly AsyncCall<TRequest, TResponse> call;
 
diff --git a/src/csharp/Grpc.Core/Internal/ClientResponseStream.cs b/src/csharp/Grpc.Core/Internal/ClientResponseStream.cs
index 7fa511faa8..b2378cade6 100644
--- a/src/csharp/Grpc.Core/Internal/ClientResponseStream.cs
+++ b/src/csharp/Grpc.Core/Internal/ClientResponseStream.cs
@@ -38,6 +38,8 @@ using System.Threading.Tasks;
 namespace Grpc.Core.Internal
 {
     internal class ClientResponseStream<TRequest, TResponse> : IAsyncStreamReader<TResponse>
+        where TRequest : class
+        where TResponse : class
     {
         readonly AsyncCall<TRequest, TResponse> call;
 
diff --git a/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs b/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs
index 01b2a11369..2bef6e68b7 100644
--- a/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs
+++ b/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs
@@ -45,6 +45,8 @@ namespace Grpc.Core.Internal
     }
 
     internal class UnaryServerCallHandler<TRequest, TResponse> : IServerCallHandler
+        where TRequest : class
+        where TResponse : class
     {
         readonly Method<TRequest, TResponse> method;
         readonly UnaryServerMethod<TRequest, TResponse> handler;
@@ -93,6 +95,8 @@ namespace Grpc.Core.Internal
     }
 
     internal class ServerStreamingServerCallHandler<TRequest, TResponse> : IServerCallHandler
+        where TRequest : class
+        where TResponse : class
     {
         readonly Method<TRequest, TResponse> method;
         readonly ServerStreamingServerMethod<TRequest, TResponse> handler;
@@ -142,6 +146,8 @@ namespace Grpc.Core.Internal
     }
 
     internal class ClientStreamingServerCallHandler<TRequest, TResponse> : IServerCallHandler
+        where TRequest : class
+        where TResponse : class
     {
         readonly Method<TRequest, TResponse> method;
         readonly ClientStreamingServerMethod<TRequest, TResponse> handler;
@@ -195,6 +201,8 @@ namespace Grpc.Core.Internal
     }
 
     internal class DuplexStreamingServerCallHandler<TRequest, TResponse> : IServerCallHandler
+        where TRequest : class
+        where TResponse : class
     {
         readonly Method<TRequest, TResponse> method;
         readonly DuplexStreamingServerMethod<TRequest, TResponse> handler;
diff --git a/src/csharp/Grpc.Core/Internal/ServerCalls.cs b/src/csharp/Grpc.Core/Internal/ServerCalls.cs
index 5c6b335c7f..81279678b9 100644
--- a/src/csharp/Grpc.Core/Internal/ServerCalls.cs
+++ b/src/csharp/Grpc.Core/Internal/ServerCalls.cs
@@ -41,21 +41,29 @@ namespace Grpc.Core.Internal
     internal static class ServerCalls
     {
         public static IServerCallHandler UnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, UnaryServerMethod<TRequest, TResponse> handler)
+            where TRequest : class
+            where TResponse : class
         {
             return new UnaryServerCallHandler<TRequest, TResponse>(method, handler);
         }
 
         public static IServerCallHandler ClientStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, ClientStreamingServerMethod<TRequest, TResponse> handler)
+            where TRequest : class
+            where TResponse : class
         {
             return new ClientStreamingServerCallHandler<TRequest, TResponse>(method, handler);
         }
 
         public static IServerCallHandler ServerStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, ServerStreamingServerMethod<TRequest, TResponse> handler)
+            where TRequest : class
+            where TResponse : class
         {
             return new ServerStreamingServerCallHandler<TRequest, TResponse>(method, handler);
         }
 
         public static IServerCallHandler DuplexStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, DuplexStreamingServerMethod<TRequest, TResponse> handler)
+            where TRequest : class
+            where TResponse : class
         {
             return new DuplexStreamingServerCallHandler<TRequest, TResponse>(method, handler);
         }
diff --git a/src/csharp/Grpc.Core/Internal/ServerRequestStream.cs b/src/csharp/Grpc.Core/Internal/ServerRequestStream.cs
index aa311059c3..d9ee0c815b 100644
--- a/src/csharp/Grpc.Core/Internal/ServerRequestStream.cs
+++ b/src/csharp/Grpc.Core/Internal/ServerRequestStream.cs
@@ -38,6 +38,8 @@ using System.Threading.Tasks;
 namespace Grpc.Core.Internal
 {
     internal class ServerRequestStream<TRequest, TResponse> : IAsyncStreamReader<TRequest>
+        where TRequest : class
+        where TResponse : class
     {
         readonly AsyncCallServer<TRequest, TResponse> call;
 
diff --git a/src/csharp/Grpc.Core/Internal/ServerResponseStream.cs b/src/csharp/Grpc.Core/Internal/ServerResponseStream.cs
index 686017c048..da688d504f 100644
--- a/src/csharp/Grpc.Core/Internal/ServerResponseStream.cs
+++ b/src/csharp/Grpc.Core/Internal/ServerResponseStream.cs
@@ -39,6 +39,8 @@ namespace Grpc.Core.Internal
     /// Writes responses asynchronously to an underlying AsyncCallServer object.
     /// </summary>
     internal class ServerResponseStream<TRequest, TResponse> : IServerStreamWriter<TResponse>
+        where TRequest : class
+        where TResponse : class
     {
         readonly AsyncCallServer<TRequest, TResponse> call;
 
diff --git a/src/csharp/Grpc.Core/ServerMethods.cs b/src/csharp/Grpc.Core/ServerMethods.cs
index 6646bb5a89..291835671f 100644
--- a/src/csharp/Grpc.Core/ServerMethods.cs
+++ b/src/csharp/Grpc.Core/ServerMethods.cs
@@ -42,20 +42,28 @@ namespace Grpc.Core
     /// <summary>
     /// Server-side handler for unary call.
     /// </summary>
-    public delegate Task<TResponse> UnaryServerMethod<TRequest, TResponse>(TRequest request);
+    public delegate Task<TResponse> UnaryServerMethod<TRequest, TResponse>(TRequest request)
+        where TRequest : class
+        where TResponse : class;
 
     /// <summary>
     /// Server-side handler for client streaming call.
     /// </summary>
-    public delegate Task<TResponse> ClientStreamingServerMethod<TRequest, TResponse>(IAsyncStreamReader<TRequest> requestStream);
+    public delegate Task<TResponse> ClientStreamingServerMethod<TRequest, TResponse>(IAsyncStreamReader<TRequest> requestStream)
+        where TRequest : class
+        where TResponse : class;
 
     /// <summary>
     /// Server-side handler for server streaming call.
     /// </summary>
-    public delegate Task ServerStreamingServerMethod<TRequest, TResponse>(TRequest request, IServerStreamWriter<TResponse> responseStream);
+    public delegate Task ServerStreamingServerMethod<TRequest, TResponse>(TRequest request, IServerStreamWriter<TResponse> responseStream)
+        where TRequest : class
+        where TResponse : class;
 
     /// <summary>
     /// Server-side handler for bidi streaming call.
     /// </summary>
-    public delegate Task DuplexStreamingServerMethod<TRequest, TResponse>(IAsyncStreamReader<TRequest> requestStream, IServerStreamWriter<TResponse> responseStream);
+    public delegate Task DuplexStreamingServerMethod<TRequest, TResponse>(IAsyncStreamReader<TRequest> requestStream, IServerStreamWriter<TResponse> responseStream)
+        where TRequest : class
+        where TResponse : class;
 }
diff --git a/src/csharp/Grpc.Core/ServerServiceDefinition.cs b/src/csharp/Grpc.Core/ServerServiceDefinition.cs
index 01b1dc8f7b..81846beb2f 100644
--- a/src/csharp/Grpc.Core/ServerServiceDefinition.cs
+++ b/src/csharp/Grpc.Core/ServerServiceDefinition.cs
@@ -76,6 +76,8 @@ namespace Grpc.Core
             public Builder AddMethod<TRequest, TResponse>(
                 Method<TRequest, TResponse> method,
                 UnaryServerMethod<TRequest, TResponse> handler)
+                    where TRequest : class
+                    where TResponse : class
             {
                 callHandlers.Add(GetFullMethodName(serviceName, method.Name), ServerCalls.UnaryCall(method, handler));
                 return this;
@@ -84,6 +86,8 @@ namespace Grpc.Core
             public Builder AddMethod<TRequest, TResponse>(
                 Method<TRequest, TResponse> method,
                 ClientStreamingServerMethod<TRequest, TResponse> handler)
+                    where TRequest : class
+                    where TResponse : class
             {
                 callHandlers.Add(GetFullMethodName(serviceName, method.Name), ServerCalls.ClientStreamingCall(method, handler));
                 return this;
@@ -92,6 +96,8 @@ namespace Grpc.Core
             public Builder AddMethod<TRequest, TResponse>(
                 Method<TRequest, TResponse> method,
                 ServerStreamingServerMethod<TRequest, TResponse> handler)
+                    where TRequest : class
+                    where TResponse : class
             {
                 callHandlers.Add(GetFullMethodName(serviceName, method.Name), ServerCalls.ServerStreamingCall(method, handler));
                 return this;
@@ -100,6 +106,8 @@ namespace Grpc.Core
             public Builder AddMethod<TRequest, TResponse>(
                 Method<TRequest, TResponse> method,
                 DuplexStreamingServerMethod<TRequest, TResponse> handler)
+                    where TRequest : class
+                    where TResponse : class
             {
                 callHandlers.Add(GetFullMethodName(serviceName, method.Name), ServerCalls.DuplexStreamingCall(method, handler));
                 return this;
diff --git a/src/csharp/Grpc.Core/Stub/AbstractStub.cs b/src/csharp/Grpc.Core/Stub/AbstractStub.cs
index cf5ab958c5..4a8b254357 100644
--- a/src/csharp/Grpc.Core/Stub/AbstractStub.cs
+++ b/src/csharp/Grpc.Core/Stub/AbstractStub.cs
@@ -64,6 +64,8 @@ namespace Grpc.Core
         /// Creates a new call to given method.
         /// </summary>
         protected Call<TRequest, TResponse> CreateCall<TRequest, TResponse>(string serviceName, Method<TRequest, TResponse> method)
+            where TRequest : class
+            where TResponse : class
         {
             var headerBuilder = Metadata.CreateBuilder();
             config.HeaderInterceptor(headerBuilder);
-- 
GitLab