diff --git a/src/csharp/Grpc.IntegrationTesting/Empty.cs b/src/csharp/Grpc.IntegrationTesting/Empty.cs
index 7169ee2..fc8ea38 100644
--- a/src/csharp/Grpc.IntegrationTesting/Empty.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Empty.cs
@@ -1,47 +1,34 @@
-// Generated by ProtoGen, Version=2.4.1.521, Culture=neutral, PublicKeyToken=17b3b1f090c3ea48.  DO NOT EDIT!
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: empty.proto
 #pragma warning disable 1591, 0612, 3021
 #region Designer generated code
 
-using pb = global::Google.ProtocolBuffers;
-using pbc = global::Google.ProtocolBuffers.Collections;
-using pbd = global::Google.ProtocolBuffers.Descriptors;
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
 using scg = global::System.Collections.Generic;
-namespace grpc.testing {
+namespace Grpc.Testing {
 
   namespace Proto {
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
     public static partial class Empty {
 
-      #region Extension registration
-      public static void RegisterAllExtensions(pb::ExtensionRegistry registry) {
-      }
-      #endregion
-      #region Static variables
-      internal static pbd::MessageDescriptor internal__static_grpc_testing_Empty__Descriptor;
-      internal static pb::FieldAccess.FieldAccessorTable<global::grpc.testing.Empty, global::grpc.testing.Empty.Builder> internal__static_grpc_testing_Empty__FieldAccessorTable;
-      #endregion
       #region Descriptor
-      public static pbd::FileDescriptor Descriptor {
+      public static pbr::FileDescriptor Descriptor {
         get { return descriptor; }
       }
-      private static pbd::FileDescriptor descriptor;
+      private static pbr::FileDescriptor descriptor;
 
       static Empty() {
         byte[] descriptorData = global::System.Convert.FromBase64String(
             string.Concat(
-            "CgtlbXB0eS5wcm90bxIMZ3JwYy50ZXN0aW5nIgcKBUVtcHR5"));
-        pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {
-          descriptor = root;
-          internal__static_grpc_testing_Empty__Descriptor = Descriptor.MessageTypes[0];
-          internal__static_grpc_testing_Empty__FieldAccessorTable =
-              new pb::FieldAccess.FieldAccessorTable<global::grpc.testing.Empty, global::grpc.testing.Empty.Builder>(internal__static_grpc_testing_Empty__Descriptor,
-                  new string[] { });
-          return null;
-        };
-        pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
-            new pbd::FileDescriptor[] {
-            }, assigner);
+              "CgtlbXB0eS5wcm90bxIMZ3JwYy50ZXN0aW5nIgcKBUVtcHR5YgZwcm90bzM="));
+        descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
+            new pbr::FileDescriptor[] { },
+            new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
+              new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.Empty), null, null, null, null)
+            }));
       }
       #endregion
 
@@ -49,230 +36,83 @@
   }
   #region Messages
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class Empty : pb::GeneratedMessage<Empty, Empty.Builder> {
-    private Empty() { }
-    private static readonly Empty defaultInstance = new Empty().MakeReadOnly();
-    private static readonly string[] _emptyFieldNames = new string[] {  };
-    private static readonly uint[] _emptyFieldTags = new uint[] {  };
-    public static Empty DefaultInstance {
-      get { return defaultInstance; }
+  public sealed partial class Empty : pb::IMessage<Empty> {
+    private static readonly pb::MessageParser<Empty> _parser = new pb::MessageParser<Empty>(() => new Empty());
+    public static pb::MessageParser<Empty> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.Proto.Empty.Descriptor.MessageTypes[0]; }
     }
 
-    public override Empty DefaultInstanceForType {
-      get { return DefaultInstance; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
-    protected override Empty ThisMessage {
-      get { return this; }
+    public Empty() {
+      OnConstruction();
     }
 
-    public static pbd::MessageDescriptor Descriptor {
-      get { return global::grpc.testing.Proto.Empty.internal__static_grpc_testing_Empty__Descriptor; }
+    partial void OnConstruction();
+
+    public Empty(Empty other) : this() {
     }
 
-    protected override pb::FieldAccess.FieldAccessorTable<Empty, Empty.Builder> InternalFieldAccessors {
-      get { return global::grpc.testing.Proto.Empty.internal__static_grpc_testing_Empty__FieldAccessorTable; }
+    public Empty Clone() {
+      return new Empty(this);
     }
 
-    public override bool IsInitialized {
-      get {
+    public override bool Equals(object other) {
+      return Equals(other as Empty);
+    }
+
+    public bool Equals(Empty other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
         return true;
       }
+      return true;
     }
 
-    public override void WriteTo(pb::ICodedOutputStream output) {
-      int size = SerializedSize;
-      string[] field_names = _emptyFieldNames;
-      UnknownFields.WriteTo(output);
+    public override int GetHashCode() {
+      int hash = 1;
+      return hash;
     }
 
-    private int memoizedSerializedSize = -1;
-    public override int SerializedSize {
-      get {
-        int size = memoizedSerializedSize;
-        if (size != -1) return size;
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
 
-        size = 0;
-        size += UnknownFields.SerializedSize;
-        memoizedSerializedSize = size;
-        return size;
+    public void WriteTo(pb::CodedOutputStream output) {
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      return size;
+    }
+
+    public void MergeFrom(Empty other) {
+      if (other == null) {
+        return;
       }
     }
 
-    public static Empty ParseFrom(pb::ByteString data) {
-      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
-    }
-    public static Empty ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
-    }
-    public static Empty ParseFrom(byte[] data) {
-      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
-    }
-    public static Empty ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
-    }
-    public static Empty ParseFrom(global::System.IO.Stream input) {
-      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
-    }
-    public static Empty ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
-    }
-    public static Empty ParseDelimitedFrom(global::System.IO.Stream input) {
-      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
-    }
-    public static Empty ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
-      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
-    }
-    public static Empty ParseFrom(pb::ICodedInputStream input) {
-      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
-    }
-    public static Empty ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
-    }
-    private Empty MakeReadOnly() {
-      return this;
-    }
-
-    public static Builder CreateBuilder() { return new Builder(); }
-    public override Builder ToBuilder() { return CreateBuilder(this); }
-    public override Builder CreateBuilderForType() { return new Builder(); }
-    public static Builder CreateBuilder(Empty prototype) {
-      return new Builder(prototype);
-    }
-
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-    public sealed partial class Builder : pb::GeneratedBuilder<Empty, Builder> {
-      protected override Builder ThisBuilder {
-        get { return this; }
-      }
-      public Builder() {
-        result = DefaultInstance;
-        resultIsReadOnly = true;
-      }
-      internal Builder(Empty cloneFrom) {
-        result = cloneFrom;
-        resultIsReadOnly = true;
-      }
-
-      private bool resultIsReadOnly;
-      private Empty result;
-
-      private Empty PrepareBuilder() {
-        if (resultIsReadOnly) {
-          Empty original = result;
-          result = new Empty();
-          resultIsReadOnly = false;
-          MergeFrom(original);
-        }
-        return result;
-      }
-
-      public override bool IsInitialized {
-        get { return result.IsInitialized; }
-      }
-
-      protected override Empty MessageBeingBuilt {
-        get { return PrepareBuilder(); }
-      }
-
-      public override Builder Clear() {
-        result = DefaultInstance;
-        resultIsReadOnly = true;
-        return this;
-      }
-
-      public override Builder Clone() {
-        if (resultIsReadOnly) {
-          return new Builder(result);
-        } else {
-          return new Builder().MergeFrom(result);
-        }
-      }
-
-      public override pbd::MessageDescriptor DescriptorForType {
-        get { return global::grpc.testing.Empty.Descriptor; }
-      }
-
-      public override Empty DefaultInstanceForType {
-        get { return global::grpc.testing.Empty.DefaultInstance; }
-      }
-
-      public override Empty BuildPartial() {
-        if (resultIsReadOnly) {
-          return result;
-        }
-        resultIsReadOnly = true;
-        return result.MakeReadOnly();
-      }
-
-      public override Builder MergeFrom(pb::IMessage other) {
-        if (other is Empty) {
-          return MergeFrom((Empty) other);
-        } else {
-          base.MergeFrom(other);
-          return this;
-        }
-      }
-
-      public override Builder MergeFrom(Empty other) {
-        if (other == global::grpc.testing.Empty.DefaultInstance) return this;
-        PrepareBuilder();
-        this.MergeUnknownFields(other.UnknownFields);
-        return this;
-      }
-
-      public override Builder MergeFrom(pb::ICodedInputStream input) {
-        return MergeFrom(input, pb::ExtensionRegistry.Empty);
-      }
-
-      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
-        PrepareBuilder();
-        pb::UnknownFieldSet.Builder unknownFields = null;
-        uint tag;
-        string field_name;
-        while (input.ReadTag(out tag, out field_name)) {
-          if(tag == 0 && field_name != null) {
-            int field_ordinal = global::System.Array.BinarySearch(_emptyFieldNames, field_name, global::System.StringComparer.Ordinal);
-            if(field_ordinal >= 0)
-              tag = _emptyFieldTags[field_ordinal];
-            else {
-              if (unknownFields == null) {
-                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
-              }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
-              continue;
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while (input.ReadTag(out tag)) {
+        switch(tag) {
+          case 0:
+            throw pb::InvalidProtocolBufferException.InvalidTag();
+          default:
+            if (pb::WireFormat.IsEndGroupTag(tag)) {
+              return;
             }
-          }
-          switch (tag) {
-            case 0: {
-              throw pb::InvalidProtocolBufferException.InvalidTag();
-            }
-            default: {
-              if (pb::WireFormat.IsEndGroupTag(tag)) {
-                if (unknownFields != null) {
-                  this.UnknownFields = unknownFields.Build();
-                }
-                return this;
-              }
-              if (unknownFields == null) {
-                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
-              }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
-              break;
-            }
-          }
+            break;
         }
-
-        if (unknownFields != null) {
-          this.UnknownFields = unknownFields.Build();
-        }
-        return this;
       }
+    }
 
-    }
-    static Empty() {
-      object.ReferenceEquals(global::grpc.testing.Proto.Empty.Descriptor, null);
-    }
   }
 
   #endregion
diff --git a/src/csharp/Grpc.IntegrationTesting/Messages.cs b/src/csharp/Grpc.IntegrationTesting/Messages.cs
index 386f377..e5a9f38 100644
--- a/src/csharp/Grpc.IntegrationTesting/Messages.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Messages.cs
@@ -1,106 +1,58 @@
-// Generated by ProtoGen, Version=2.4.1.521, Culture=neutral, PublicKeyToken=17b3b1f090c3ea48.  DO NOT EDIT!
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: messages.proto
 #pragma warning disable 1591, 0612, 3021
 #region Designer generated code
 
-using pb = global::Google.ProtocolBuffers;
-using pbc = global::Google.ProtocolBuffers.Collections;
-using pbd = global::Google.ProtocolBuffers.Descriptors;
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
 using scg = global::System.Collections.Generic;
-namespace grpc.testing {
+namespace Grpc.Testing {
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
   public static partial class Messages {
 
-    #region Extension registration
-    public static void RegisterAllExtensions(pb::ExtensionRegistry registry) {
-    }
-    #endregion
-    #region Static variables
-    internal static pbd::MessageDescriptor internal__static_grpc_testing_Payload__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::grpc.testing.Payload, global::grpc.testing.Payload.Builder> internal__static_grpc_testing_Payload__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_grpc_testing_SimpleRequest__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::grpc.testing.SimpleRequest, global::grpc.testing.SimpleRequest.Builder> internal__static_grpc_testing_SimpleRequest__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_grpc_testing_SimpleResponse__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::grpc.testing.SimpleResponse, global::grpc.testing.SimpleResponse.Builder> internal__static_grpc_testing_SimpleResponse__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_grpc_testing_StreamingInputCallRequest__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::grpc.testing.StreamingInputCallRequest, global::grpc.testing.StreamingInputCallRequest.Builder> internal__static_grpc_testing_StreamingInputCallRequest__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_grpc_testing_StreamingInputCallResponse__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::grpc.testing.StreamingInputCallResponse, global::grpc.testing.StreamingInputCallResponse.Builder> internal__static_grpc_testing_StreamingInputCallResponse__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_grpc_testing_ResponseParameters__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::grpc.testing.ResponseParameters, global::grpc.testing.ResponseParameters.Builder> internal__static_grpc_testing_ResponseParameters__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_grpc_testing_StreamingOutputCallRequest__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallRequest.Builder> internal__static_grpc_testing_StreamingOutputCallRequest__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_grpc_testing_StreamingOutputCallResponse__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::grpc.testing.StreamingOutputCallResponse, global::grpc.testing.StreamingOutputCallResponse.Builder> internal__static_grpc_testing_StreamingOutputCallResponse__FieldAccessorTable;
-    #endregion
     #region Descriptor
-    public static pbd::FileDescriptor Descriptor {
+    public static pbr::FileDescriptor Descriptor {
       get { return descriptor; }
     }
-    private static pbd::FileDescriptor descriptor;
+    private static pbr::FileDescriptor descriptor;
 
     static Messages() {
       byte[] descriptorData = global::System.Convert.FromBase64String(
           string.Concat(
-            "Cg5tZXNzYWdlcy5wcm90bxIMZ3JwYy50ZXN0aW5nIkAKB1BheWxvYWQSJwoE",
-            "dHlwZRgBIAEoDjIZLmdycGMudGVzdGluZy5QYXlsb2FkVHlwZRIMCgRib2R5",
-            "GAIgASgMIrEBCg1TaW1wbGVSZXF1ZXN0EjAKDXJlc3BvbnNlX3R5cGUYASAB",
-            "KA4yGS5ncnBjLnRlc3RpbmcuUGF5bG9hZFR5cGUSFQoNcmVzcG9uc2Vfc2l6",
-            "ZRgCIAEoBRImCgdwYXlsb2FkGAMgASgLMhUuZ3JwYy50ZXN0aW5nLlBheWxv",
-            "YWQSFQoNZmlsbF91c2VybmFtZRgEIAEoCBIYChBmaWxsX29hdXRoX3Njb3Bl",
-            "GAUgASgIIl8KDlNpbXBsZVJlc3BvbnNlEiYKB3BheWxvYWQYASABKAsyFS5n",
-            "cnBjLnRlc3RpbmcuUGF5bG9hZBIQCgh1c2VybmFtZRgCIAEoCRITCgtvYXV0",
-            "aF9zY29wZRgDIAEoCSJDChlTdHJlYW1pbmdJbnB1dENhbGxSZXF1ZXN0EiYK",
-            "B3BheWxvYWQYASABKAsyFS5ncnBjLnRlc3RpbmcuUGF5bG9hZCI9ChpTdHJl",
-            "YW1pbmdJbnB1dENhbGxSZXNwb25zZRIfChdhZ2dyZWdhdGVkX3BheWxvYWRf",
-            "c2l6ZRgBIAEoBSI3ChJSZXNwb25zZVBhcmFtZXRlcnMSDAoEc2l6ZRgBIAEo",
-            "BRITCgtpbnRlcnZhbF91cxgCIAEoBSK1AQoaU3RyZWFtaW5nT3V0cHV0Q2Fs",
-            "bFJlcXVlc3QSMAoNcmVzcG9uc2VfdHlwZRgBIAEoDjIZLmdycGMudGVzdGlu",
-            "Zy5QYXlsb2FkVHlwZRI9ChNyZXNwb25zZV9wYXJhbWV0ZXJzGAIgAygLMiAu",
-            "Z3JwYy50ZXN0aW5nLlJlc3BvbnNlUGFyYW1ldGVycxImCgdwYXlsb2FkGAMg",
-            "ASgLMhUuZ3JwYy50ZXN0aW5nLlBheWxvYWQiRQobU3RyZWFtaW5nT3V0cHV0",
-            "Q2FsbFJlc3BvbnNlEiYKB3BheWxvYWQYASABKAsyFS5ncnBjLnRlc3Rpbmcu",
-            "UGF5bG9hZCo/CgtQYXlsb2FkVHlwZRIQCgxDT01QUkVTU0FCTEUQABISCg5V",
-          "TkNPTVBSRVNTQUJMRRABEgoKBlJBTkRPTRAC"));
-      pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {
-        descriptor = root;
-        internal__static_grpc_testing_Payload__Descriptor = Descriptor.MessageTypes[0];
-        internal__static_grpc_testing_Payload__FieldAccessorTable =
-            new pb::FieldAccess.FieldAccessorTable<global::grpc.testing.Payload, global::grpc.testing.Payload.Builder>(internal__static_grpc_testing_Payload__Descriptor,
-                new string[] { "Type", "Body", });
-        internal__static_grpc_testing_SimpleRequest__Descriptor = Descriptor.MessageTypes[1];
-        internal__static_grpc_testing_SimpleRequest__FieldAccessorTable =
-            new pb::FieldAccess.FieldAccessorTable<global::grpc.testing.SimpleRequest, global::grpc.testing.SimpleRequest.Builder>(internal__static_grpc_testing_SimpleRequest__Descriptor,
-                new string[] { "ResponseType", "ResponseSize", "Payload", "FillUsername", "FillOauthScope", });
-        internal__static_grpc_testing_SimpleResponse__Descriptor = Descriptor.MessageTypes[2];
-        internal__static_grpc_testing_SimpleResponse__FieldAccessorTable =
-            new pb::FieldAccess.FieldAccessorTable<global::grpc.testing.SimpleResponse, global::grpc.testing.SimpleResponse.Builder>(internal__static_grpc_testing_SimpleResponse__Descriptor,
-                new string[] { "Payload", "Username", "OauthScope", });
-        internal__static_grpc_testing_StreamingInputCallRequest__Descriptor = Descriptor.MessageTypes[3];
-        internal__static_grpc_testing_StreamingInputCallRequest__FieldAccessorTable =
-            new pb::FieldAccess.FieldAccessorTable<global::grpc.testing.StreamingInputCallRequest, global::grpc.testing.StreamingInputCallRequest.Builder>(internal__static_grpc_testing_StreamingInputCallRequest__Descriptor,
-                new string[] { "Payload", });
-        internal__static_grpc_testing_StreamingInputCallResponse__Descriptor = Descriptor.MessageTypes[4];
-        internal__static_grpc_testing_StreamingInputCallResponse__FieldAccessorTable =
-            new pb::FieldAccess.FieldAccessorTable<global::grpc.testing.StreamingInputCallResponse, global::grpc.testing.StreamingInputCallResponse.Builder>(internal__static_grpc_testing_StreamingInputCallResponse__Descriptor,
-                new string[] { "AggregatedPayloadSize", });
-        internal__static_grpc_testing_ResponseParameters__Descriptor = Descriptor.MessageTypes[5];
-        internal__static_grpc_testing_ResponseParameters__FieldAccessorTable =
-            new pb::FieldAccess.FieldAccessorTable<global::grpc.testing.ResponseParameters, global::grpc.testing.ResponseParameters.Builder>(internal__static_grpc_testing_ResponseParameters__Descriptor,
-                new string[] { "Size", "IntervalUs", });
-        internal__static_grpc_testing_StreamingOutputCallRequest__Descriptor = Descriptor.MessageTypes[6];
-        internal__static_grpc_testing_StreamingOutputCallRequest__FieldAccessorTable =
-            new pb::FieldAccess.FieldAccessorTable<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallRequest.Builder>(internal__static_grpc_testing_StreamingOutputCallRequest__Descriptor,
-                new string[] { "ResponseType", "ResponseParameters", "Payload", });
-        internal__static_grpc_testing_StreamingOutputCallResponse__Descriptor = Descriptor.MessageTypes[7];
-        internal__static_grpc_testing_StreamingOutputCallResponse__FieldAccessorTable =
-            new pb::FieldAccess.FieldAccessorTable<global::grpc.testing.StreamingOutputCallResponse, global::grpc.testing.StreamingOutputCallResponse.Builder>(internal__static_grpc_testing_StreamingOutputCallResponse__Descriptor,
-                new string[] { "Payload", });
-        return null;
-      };
-      pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
-          new pbd::FileDescriptor[] {
-          }, assigner);
+            "Cg5tZXNzYWdlcy5wcm90bxIMZ3JwYy50ZXN0aW5nIkAKB1BheWxvYWQSJwoE", 
+            "dHlwZRgBIAEoDjIZLmdycGMudGVzdGluZy5QYXlsb2FkVHlwZRIMCgRib2R5", 
+            "GAIgASgMIrEBCg1TaW1wbGVSZXF1ZXN0EjAKDXJlc3BvbnNlX3R5cGUYASAB", 
+            "KA4yGS5ncnBjLnRlc3RpbmcuUGF5bG9hZFR5cGUSFQoNcmVzcG9uc2Vfc2l6", 
+            "ZRgCIAEoBRImCgdwYXlsb2FkGAMgASgLMhUuZ3JwYy50ZXN0aW5nLlBheWxv", 
+            "YWQSFQoNZmlsbF91c2VybmFtZRgEIAEoCBIYChBmaWxsX29hdXRoX3Njb3Bl", 
+            "GAUgASgIIl8KDlNpbXBsZVJlc3BvbnNlEiYKB3BheWxvYWQYASABKAsyFS5n", 
+            "cnBjLnRlc3RpbmcuUGF5bG9hZBIQCgh1c2VybmFtZRgCIAEoCRITCgtvYXV0", 
+            "aF9zY29wZRgDIAEoCSJDChlTdHJlYW1pbmdJbnB1dENhbGxSZXF1ZXN0EiYK", 
+            "B3BheWxvYWQYASABKAsyFS5ncnBjLnRlc3RpbmcuUGF5bG9hZCI9ChpTdHJl", 
+            "YW1pbmdJbnB1dENhbGxSZXNwb25zZRIfChdhZ2dyZWdhdGVkX3BheWxvYWRf", 
+            "c2l6ZRgBIAEoBSI3ChJSZXNwb25zZVBhcmFtZXRlcnMSDAoEc2l6ZRgBIAEo", 
+            "BRITCgtpbnRlcnZhbF91cxgCIAEoBSK1AQoaU3RyZWFtaW5nT3V0cHV0Q2Fs", 
+            "bFJlcXVlc3QSMAoNcmVzcG9uc2VfdHlwZRgBIAEoDjIZLmdycGMudGVzdGlu", 
+            "Zy5QYXlsb2FkVHlwZRI9ChNyZXNwb25zZV9wYXJhbWV0ZXJzGAIgAygLMiAu", 
+            "Z3JwYy50ZXN0aW5nLlJlc3BvbnNlUGFyYW1ldGVycxImCgdwYXlsb2FkGAMg", 
+            "ASgLMhUuZ3JwYy50ZXN0aW5nLlBheWxvYWQiRQobU3RyZWFtaW5nT3V0cHV0", 
+            "Q2FsbFJlc3BvbnNlEiYKB3BheWxvYWQYASABKAsyFS5ncnBjLnRlc3Rpbmcu", 
+            "UGF5bG9hZCo/CgtQYXlsb2FkVHlwZRIQCgxDT01QUkVTU0FCTEUQABISCg5V", 
+            "TkNPTVBSRVNTQUJMRRABEgoKBlJBTkRPTRACYgZwcm90bzM="));
+      descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
+          new pbr::FileDescriptor[] { },
+          new pbr::GeneratedCodeInfo(new[] {typeof(global::Grpc.Testing.PayloadType), }, new pbr::GeneratedCodeInfo[] {
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.Payload), new[]{ "Type", "Body" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.SimpleRequest), new[]{ "ResponseType", "ResponseSize", "Payload", "FillUsername", "FillOauthScope" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.SimpleResponse), new[]{ "Payload", "Username", "OauthScope" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.StreamingInputCallRequest), new[]{ "Payload" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.StreamingInputCallResponse), new[]{ "AggregatedPayloadSize" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ResponseParameters), new[]{ "Size", "IntervalUs" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.StreamingOutputCallRequest), new[]{ "ResponseType", "ResponseParameters", "Payload" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.StreamingOutputCallResponse), new[]{ "Payload" }, null, null, null)
+          }));
     }
     #endregion
 
@@ -116,2772 +68,1133 @@
 
   #region Messages
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class Payload : pb::GeneratedMessage<Payload, Payload.Builder> {
-    private Payload() { }
-    private static readonly Payload defaultInstance = new Payload().MakeReadOnly();
-    private static readonly string[] _payloadFieldNames = new string[] { "body", "type" };
-    private static readonly uint[] _payloadFieldTags = new uint[] { 18, 8 };
-    public static Payload DefaultInstance {
-      get { return defaultInstance; }
+  public sealed partial class Payload : pb::IMessage<Payload> {
+    private static readonly pb::MessageParser<Payload> _parser = new pb::MessageParser<Payload>(() => new Payload());
+    public static pb::MessageParser<Payload> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.Messages.Descriptor.MessageTypes[0]; }
     }
 
-    public override Payload DefaultInstanceForType {
-      get { return DefaultInstance; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
-    protected override Payload ThisMessage {
-      get { return this; }
+    public Payload() {
+      OnConstruction();
     }
 
-    public static pbd::MessageDescriptor Descriptor {
-      get { return global::grpc.testing.Messages.internal__static_grpc_testing_Payload__Descriptor; }
+    partial void OnConstruction();
+
+    public Payload(Payload other) : this() {
+      type_ = other.type_;
+      body_ = other.body_;
     }
 
-    protected override pb::FieldAccess.FieldAccessorTable<Payload, Payload.Builder> InternalFieldAccessors {
-      get { return global::grpc.testing.Messages.internal__static_grpc_testing_Payload__FieldAccessorTable; }
+    public Payload Clone() {
+      return new Payload(this);
     }
 
     public const int TypeFieldNumber = 1;
-    private bool hasType;
-    private global::grpc.testing.PayloadType type_ = global::grpc.testing.PayloadType.COMPRESSABLE;
-    public bool HasType {
-      get { return hasType; }
-    }
-    public global::grpc.testing.PayloadType Type {
+    private global::Grpc.Testing.PayloadType type_ = global::Grpc.Testing.PayloadType.COMPRESSABLE;
+    public global::Grpc.Testing.PayloadType Type {
       get { return type_; }
+      set {
+        type_ = value;
+      }
     }
 
     public const int BodyFieldNumber = 2;
-    private bool hasBody;
     private pb::ByteString body_ = pb::ByteString.Empty;
-    public bool HasBody {
-      get { return hasBody; }
-    }
     public pb::ByteString Body {
       get { return body_; }
+      set {
+        body_ = pb::Preconditions.CheckNotNull(value, "value");
+      }
     }
 
-    public override bool IsInitialized {
-      get {
+    public override bool Equals(object other) {
+      return Equals(other as Payload);
+    }
+
+    public bool Equals(Payload other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
         return true;
       }
+      if (Type != other.Type) return false;
+      if (Body != other.Body) return false;
+      return true;
     }
 
-    public override void WriteTo(pb::ICodedOutputStream output) {
-      int size = SerializedSize;
-      string[] field_names = _payloadFieldNames;
-      if (hasType) {
-        output.WriteEnum(1, field_names[1], (int) Type, Type);
-      }
-      if (hasBody) {
-        output.WriteBytes(2, field_names[0], Body);
-      }
-      UnknownFields.WriteTo(output);
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Type != global::Grpc.Testing.PayloadType.COMPRESSABLE) hash ^= Type.GetHashCode();
+      if (Body.Length != 0) hash ^= Body.GetHashCode();
+      return hash;
     }
 
-    private int memoizedSerializedSize = -1;
-    public override int SerializedSize {
-      get {
-        int size = memoizedSerializedSize;
-        if (size != -1) return size;
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
 
-        size = 0;
-        if (hasType) {
-          size += pb::CodedOutputStream.ComputeEnumSize(1, (int) Type);
-        }
-        if (hasBody) {
-          size += pb::CodedOutputStream.ComputeBytesSize(2, Body);
-        }
-        size += UnknownFields.SerializedSize;
-        memoizedSerializedSize = size;
-        return size;
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Type != global::Grpc.Testing.PayloadType.COMPRESSABLE) {
+        output.WriteRawTag(8);
+        output.WriteEnum((int) Type);
+      }
+      if (Body.Length != 0) {
+        output.WriteRawTag(18);
+        output.WriteBytes(Body);
       }
     }
 
-    public static Payload ParseFrom(pb::ByteString data) {
-      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
-    }
-    public static Payload ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
-    }
-    public static Payload ParseFrom(byte[] data) {
-      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
-    }
-    public static Payload ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
-    }
-    public static Payload ParseFrom(global::System.IO.Stream input) {
-      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
-    }
-    public static Payload ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
-    }
-    public static Payload ParseDelimitedFrom(global::System.IO.Stream input) {
-      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
-    }
-    public static Payload ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
-      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
-    }
-    public static Payload ParseFrom(pb::ICodedInputStream input) {
-      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
-    }
-    public static Payload ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
-    }
-    private Payload MakeReadOnly() {
-      return this;
+    public int CalculateSize() {
+      int size = 0;
+      if (Type != global::Grpc.Testing.PayloadType.COMPRESSABLE) {
+        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Type);
+      }
+      if (Body.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeBytesSize(Body);
+      }
+      return size;
     }
 
-    public static Builder CreateBuilder() { return new Builder(); }
-    public override Builder ToBuilder() { return CreateBuilder(this); }
-    public override Builder CreateBuilderForType() { return new Builder(); }
-    public static Builder CreateBuilder(Payload prototype) {
-      return new Builder(prototype);
+    public void MergeFrom(Payload other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Type != global::Grpc.Testing.PayloadType.COMPRESSABLE) {
+        Type = other.Type;
+      }
+      if (other.Body.Length != 0) {
+        Body = other.Body;
+      }
     }
 
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-    public sealed partial class Builder : pb::GeneratedBuilder<Payload, Builder> {
-      protected override Builder ThisBuilder {
-        get { return this; }
-      }
-      public Builder() {
-        result = DefaultInstance;
-        resultIsReadOnly = true;
-      }
-      internal Builder(Payload cloneFrom) {
-        result = cloneFrom;
-        resultIsReadOnly = true;
-      }
-
-      private bool resultIsReadOnly;
-      private Payload result;
-
-      private Payload PrepareBuilder() {
-        if (resultIsReadOnly) {
-          Payload original = result;
-          result = new Payload();
-          resultIsReadOnly = false;
-          MergeFrom(original);
-        }
-        return result;
-      }
-
-      public override bool IsInitialized {
-        get { return result.IsInitialized; }
-      }
-
-      protected override Payload MessageBeingBuilt {
-        get { return PrepareBuilder(); }
-      }
-
-      public override Builder Clear() {
-        result = DefaultInstance;
-        resultIsReadOnly = true;
-        return this;
-      }
-
-      public override Builder Clone() {
-        if (resultIsReadOnly) {
-          return new Builder(result);
-        } else {
-          return new Builder().MergeFrom(result);
-        }
-      }
-
-      public override pbd::MessageDescriptor DescriptorForType {
-        get { return global::grpc.testing.Payload.Descriptor; }
-      }
-
-      public override Payload DefaultInstanceForType {
-        get { return global::grpc.testing.Payload.DefaultInstance; }
-      }
-
-      public override Payload BuildPartial() {
-        if (resultIsReadOnly) {
-          return result;
-        }
-        resultIsReadOnly = true;
-        return result.MakeReadOnly();
-      }
-
-      public override Builder MergeFrom(pb::IMessage other) {
-        if (other is Payload) {
-          return MergeFrom((Payload) other);
-        } else {
-          base.MergeFrom(other);
-          return this;
-        }
-      }
-
-      public override Builder MergeFrom(Payload other) {
-        if (other == global::grpc.testing.Payload.DefaultInstance) return this;
-        PrepareBuilder();
-        if (other.HasType) {
-          Type = other.Type;
-        }
-        if (other.HasBody) {
-          Body = other.Body;
-        }
-        this.MergeUnknownFields(other.UnknownFields);
-        return this;
-      }
-
-      public override Builder MergeFrom(pb::ICodedInputStream input) {
-        return MergeFrom(input, pb::ExtensionRegistry.Empty);
-      }
-
-      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
-        PrepareBuilder();
-        pb::UnknownFieldSet.Builder unknownFields = null;
-        uint tag;
-        string field_name;
-        while (input.ReadTag(out tag, out field_name)) {
-          if(tag == 0 && field_name != null) {
-            int field_ordinal = global::System.Array.BinarySearch(_payloadFieldNames, field_name, global::System.StringComparer.Ordinal);
-            if(field_ordinal >= 0)
-              tag = _payloadFieldTags[field_ordinal];
-            else {
-              if (unknownFields == null) {
-                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
-              }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
-              continue;
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while (input.ReadTag(out tag)) {
+        switch(tag) {
+          case 0:
+            throw pb::InvalidProtocolBufferException.InvalidTag();
+          default:
+            if (pb::WireFormat.IsEndGroupTag(tag)) {
+              return;
             }
+            break;
+          case 8: {
+            type_ = (global::Grpc.Testing.PayloadType) input.ReadEnum();
+            break;
           }
-          switch (tag) {
-            case 0: {
-              throw pb::InvalidProtocolBufferException.InvalidTag();
-            }
-            default: {
-              if (pb::WireFormat.IsEndGroupTag(tag)) {
-                if (unknownFields != null) {
-                  this.UnknownFields = unknownFields.Build();
-                }
-                return this;
-              }
-              if (unknownFields == null) {
-                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
-              }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
-              break;
-            }
-            case 8: {
-              object unknown;
-              if(input.ReadEnum(ref result.type_, out unknown)) {
-                result.hasType = true;
-              } else if(unknown is int) {
-                if (unknownFields == null) {
-                  unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
-                }
-                unknownFields.MergeVarintField(1, (ulong)(int)unknown);
-              }
-              break;
-            }
-            case 18: {
-              result.hasBody = input.ReadBytes(ref result.body_);
-              break;
-            }
+          case 18: {
+            Body = input.ReadBytes();
+            break;
           }
         }
-
-        if (unknownFields != null) {
-          this.UnknownFields = unknownFields.Build();
-        }
-        return this;
-      }
-
-
-      public bool HasType {
-       get { return result.hasType; }
-      }
-      public global::grpc.testing.PayloadType Type {
-        get { return result.Type; }
-        set { SetType(value); }
-      }
-      public Builder SetType(global::grpc.testing.PayloadType value) {
-        PrepareBuilder();
-        result.hasType = true;
-        result.type_ = value;
-        return this;
-      }
-      public Builder ClearType() {
-        PrepareBuilder();
-        result.hasType = false;
-        result.type_ = global::grpc.testing.PayloadType.COMPRESSABLE;
-        return this;
-      }
-
-      public bool HasBody {
-        get { return result.hasBody; }
-      }
-      public pb::ByteString Body {
-        get { return result.Body; }
-        set { SetBody(value); }
-      }
-      public Builder SetBody(pb::ByteString value) {
-        pb::ThrowHelper.ThrowIfNull(value, "value");
-        PrepareBuilder();
-        result.hasBody = true;
-        result.body_ = value;
-        return this;
-      }
-      public Builder ClearBody() {
-        PrepareBuilder();
-        result.hasBody = false;
-        result.body_ = pb::ByteString.Empty;
-        return this;
       }
     }
-    static Payload() {
-      object.ReferenceEquals(global::grpc.testing.Messages.Descriptor, null);
-    }
+
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class SimpleRequest : pb::GeneratedMessage<SimpleRequest, SimpleRequest.Builder> {
-    private SimpleRequest() { }
-    private static readonly SimpleRequest defaultInstance = new SimpleRequest().MakeReadOnly();
-    private static readonly string[] _simpleRequestFieldNames = new string[] { "fill_oauth_scope", "fill_username", "payload", "response_size", "response_type" };
-    private static readonly uint[] _simpleRequestFieldTags = new uint[] { 40, 32, 26, 16, 8 };
-    public static SimpleRequest DefaultInstance {
-      get { return defaultInstance; }
+  public sealed partial class SimpleRequest : pb::IMessage<SimpleRequest> {
+    private static readonly pb::MessageParser<SimpleRequest> _parser = new pb::MessageParser<SimpleRequest>(() => new SimpleRequest());
+    public static pb::MessageParser<SimpleRequest> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.Messages.Descriptor.MessageTypes[1]; }
     }
 
-    public override SimpleRequest DefaultInstanceForType {
-      get { return DefaultInstance; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
-    protected override SimpleRequest ThisMessage {
-      get { return this; }
+    public SimpleRequest() {
+      OnConstruction();
     }
 
-    public static pbd::MessageDescriptor Descriptor {
-      get { return global::grpc.testing.Messages.internal__static_grpc_testing_SimpleRequest__Descriptor; }
+    partial void OnConstruction();
+
+    public SimpleRequest(SimpleRequest other) : this() {
+      responseType_ = other.responseType_;
+      responseSize_ = other.responseSize_;
+      Payload = other.payload_ != null ? other.Payload.Clone() : null;
+      fillUsername_ = other.fillUsername_;
+      fillOauthScope_ = other.fillOauthScope_;
     }
 
-    protected override pb::FieldAccess.FieldAccessorTable<SimpleRequest, SimpleRequest.Builder> InternalFieldAccessors {
-      get { return global::grpc.testing.Messages.internal__static_grpc_testing_SimpleRequest__FieldAccessorTable; }
+    public SimpleRequest Clone() {
+      return new SimpleRequest(this);
     }
 
     public const int ResponseTypeFieldNumber = 1;
-    private bool hasResponseType;
-    private global::grpc.testing.PayloadType responseType_ = global::grpc.testing.PayloadType.COMPRESSABLE;
-    public bool HasResponseType {
-      get { return hasResponseType; }
-    }
-    public global::grpc.testing.PayloadType ResponseType {
+    private global::Grpc.Testing.PayloadType responseType_ = global::Grpc.Testing.PayloadType.COMPRESSABLE;
+    public global::Grpc.Testing.PayloadType ResponseType {
       get { return responseType_; }
+      set {
+        responseType_ = value;
+      }
     }
 
     public const int ResponseSizeFieldNumber = 2;
-    private bool hasResponseSize;
     private int responseSize_;
-    public bool HasResponseSize {
-      get { return hasResponseSize; }
-    }
     public int ResponseSize {
       get { return responseSize_; }
+      set {
+        responseSize_ = value;
+      }
     }
 
     public const int PayloadFieldNumber = 3;
-    private bool hasPayload;
-    private global::grpc.testing.Payload payload_;
-    public bool HasPayload {
-      get { return hasPayload; }
-    }
-    public global::grpc.testing.Payload Payload {
-      get { return payload_ ?? global::grpc.testing.Payload.DefaultInstance; }
+    private global::Grpc.Testing.Payload payload_;
+    public global::Grpc.Testing.Payload Payload {
+      get { return payload_; }
+      set {
+        payload_ = value;
+      }
     }
 
     public const int FillUsernameFieldNumber = 4;
-    private bool hasFillUsername;
     private bool fillUsername_;
-    public bool HasFillUsername {
-      get { return hasFillUsername; }
-    }
     public bool FillUsername {
       get { return fillUsername_; }
+      set {
+        fillUsername_ = value;
+      }
     }
 
     public const int FillOauthScopeFieldNumber = 5;
-    private bool hasFillOauthScope;
     private bool fillOauthScope_;
-    public bool HasFillOauthScope {
-      get { return hasFillOauthScope; }
-    }
     public bool FillOauthScope {
       get { return fillOauthScope_; }
+      set {
+        fillOauthScope_ = value;
+      }
     }
 
-    public override bool IsInitialized {
-      get {
+    public override bool Equals(object other) {
+      return Equals(other as SimpleRequest);
+    }
+
+    public bool Equals(SimpleRequest other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
         return true;
       }
+      if (ResponseType != other.ResponseType) return false;
+      if (ResponseSize != other.ResponseSize) return false;
+      if (!object.Equals(Payload, other.Payload)) return false;
+      if (FillUsername != other.FillUsername) return false;
+      if (FillOauthScope != other.FillOauthScope) return false;
+      return true;
     }
 
-    public override void WriteTo(pb::ICodedOutputStream output) {
-      int size = SerializedSize;
-      string[] field_names = _simpleRequestFieldNames;
-      if (hasResponseType) {
-        output.WriteEnum(1, field_names[4], (int) ResponseType, ResponseType);
-      }
-      if (hasResponseSize) {
-        output.WriteInt32(2, field_names[3], ResponseSize);
-      }
-      if (hasPayload) {
-        output.WriteMessage(3, field_names[2], Payload);
-      }
-      if (hasFillUsername) {
-        output.WriteBool(4, field_names[1], FillUsername);
-      }
-      if (hasFillOauthScope) {
-        output.WriteBool(5, field_names[0], FillOauthScope);
-      }
-      UnknownFields.WriteTo(output);
+    public override int GetHashCode() {
+      int hash = 1;
+      if (ResponseType != global::Grpc.Testing.PayloadType.COMPRESSABLE) hash ^= ResponseType.GetHashCode();
+      if (ResponseSize != 0) hash ^= ResponseSize.GetHashCode();
+      if (payload_ != null) hash ^= Payload.GetHashCode();
+      if (FillUsername != false) hash ^= FillUsername.GetHashCode();
+      if (FillOauthScope != false) hash ^= FillOauthScope.GetHashCode();
+      return hash;
     }
 
-    private int memoizedSerializedSize = -1;
-    public override int SerializedSize {
-      get {
-        int size = memoizedSerializedSize;
-        if (size != -1) return size;
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
 
-        size = 0;
-        if (hasResponseType) {
-          size += pb::CodedOutputStream.ComputeEnumSize(1, (int) ResponseType);
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (ResponseType != global::Grpc.Testing.PayloadType.COMPRESSABLE) {
+        output.WriteRawTag(8);
+        output.WriteEnum((int) ResponseType);
+      }
+      if (ResponseSize != 0) {
+        output.WriteRawTag(16);
+        output.WriteInt32(ResponseSize);
+      }
+      if (payload_ != null) {
+        output.WriteRawTag(26);
+        output.WriteMessage(Payload);
+      }
+      if (FillUsername != false) {
+        output.WriteRawTag(32);
+        output.WriteBool(FillUsername);
+      }
+      if (FillOauthScope != false) {
+        output.WriteRawTag(40);
+        output.WriteBool(FillOauthScope);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (ResponseType != global::Grpc.Testing.PayloadType.COMPRESSABLE) {
+        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ResponseType);
+      }
+      if (ResponseSize != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(ResponseSize);
+      }
+      if (payload_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload);
+      }
+      if (FillUsername != false) {
+        size += 1 + 1;
+      }
+      if (FillOauthScope != false) {
+        size += 1 + 1;
+      }
+      return size;
+    }
+
+    public void MergeFrom(SimpleRequest other) {
+      if (other == null) {
+        return;
+      }
+      if (other.ResponseType != global::Grpc.Testing.PayloadType.COMPRESSABLE) {
+        ResponseType = other.ResponseType;
+      }
+      if (other.ResponseSize != 0) {
+        ResponseSize = other.ResponseSize;
+      }
+      if (other.payload_ != null) {
+        if (payload_ == null) {
+          payload_ = new global::Grpc.Testing.Payload();
         }
-        if (hasResponseSize) {
-          size += pb::CodedOutputStream.ComputeInt32Size(2, ResponseSize);
-        }
-        if (hasPayload) {
-          size += pb::CodedOutputStream.ComputeMessageSize(3, Payload);
-        }
-        if (hasFillUsername) {
-          size += pb::CodedOutputStream.ComputeBoolSize(4, FillUsername);
-        }
-        if (hasFillOauthScope) {
-          size += pb::CodedOutputStream.ComputeBoolSize(5, FillOauthScope);
-        }
-        size += UnknownFields.SerializedSize;
-        memoizedSerializedSize = size;
-        return size;
+        Payload.MergeFrom(other.Payload);
+      }
+      if (other.FillUsername != false) {
+        FillUsername = other.FillUsername;
+      }
+      if (other.FillOauthScope != false) {
+        FillOauthScope = other.FillOauthScope;
       }
     }
 
-    public static SimpleRequest ParseFrom(pb::ByteString data) {
-      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
-    }
-    public static SimpleRequest ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
-    }
-    public static SimpleRequest ParseFrom(byte[] data) {
-      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
-    }
-    public static SimpleRequest ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
-    }
-    public static SimpleRequest ParseFrom(global::System.IO.Stream input) {
-      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
-    }
-    public static SimpleRequest ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
-    }
-    public static SimpleRequest ParseDelimitedFrom(global::System.IO.Stream input) {
-      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
-    }
-    public static SimpleRequest ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
-      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
-    }
-    public static SimpleRequest ParseFrom(pb::ICodedInputStream input) {
-      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
-    }
-    public static SimpleRequest ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
-    }
-    private SimpleRequest MakeReadOnly() {
-      return this;
-    }
-
-    public static Builder CreateBuilder() { return new Builder(); }
-    public override Builder ToBuilder() { return CreateBuilder(this); }
-    public override Builder CreateBuilderForType() { return new Builder(); }
-    public static Builder CreateBuilder(SimpleRequest prototype) {
-      return new Builder(prototype);
-    }
-
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-    public sealed partial class Builder : pb::GeneratedBuilder<SimpleRequest, Builder> {
-      protected override Builder ThisBuilder {
-        get { return this; }
-      }
-      public Builder() {
-        result = DefaultInstance;
-        resultIsReadOnly = true;
-      }
-      internal Builder(SimpleRequest cloneFrom) {
-        result = cloneFrom;
-        resultIsReadOnly = true;
-      }
-
-      private bool resultIsReadOnly;
-      private SimpleRequest result;
-
-      private SimpleRequest PrepareBuilder() {
-        if (resultIsReadOnly) {
-          SimpleRequest original = result;
-          result = new SimpleRequest();
-          resultIsReadOnly = false;
-          MergeFrom(original);
-        }
-        return result;
-      }
-
-      public override bool IsInitialized {
-        get { return result.IsInitialized; }
-      }
-
-      protected override SimpleRequest MessageBeingBuilt {
-        get { return PrepareBuilder(); }
-      }
-
-      public override Builder Clear() {
-        result = DefaultInstance;
-        resultIsReadOnly = true;
-        return this;
-      }
-
-      public override Builder Clone() {
-        if (resultIsReadOnly) {
-          return new Builder(result);
-        } else {
-          return new Builder().MergeFrom(result);
-        }
-      }
-
-      public override pbd::MessageDescriptor DescriptorForType {
-        get { return global::grpc.testing.SimpleRequest.Descriptor; }
-      }
-
-      public override SimpleRequest DefaultInstanceForType {
-        get { return global::grpc.testing.SimpleRequest.DefaultInstance; }
-      }
-
-      public override SimpleRequest BuildPartial() {
-        if (resultIsReadOnly) {
-          return result;
-        }
-        resultIsReadOnly = true;
-        return result.MakeReadOnly();
-      }
-
-      public override Builder MergeFrom(pb::IMessage other) {
-        if (other is SimpleRequest) {
-          return MergeFrom((SimpleRequest) other);
-        } else {
-          base.MergeFrom(other);
-          return this;
-        }
-      }
-
-      public override Builder MergeFrom(SimpleRequest other) {
-        if (other == global::grpc.testing.SimpleRequest.DefaultInstance) return this;
-        PrepareBuilder();
-        if (other.HasResponseType) {
-          ResponseType = other.ResponseType;
-        }
-        if (other.HasResponseSize) {
-          ResponseSize = other.ResponseSize;
-        }
-        if (other.HasPayload) {
-          MergePayload(other.Payload);
-        }
-        if (other.HasFillUsername) {
-          FillUsername = other.FillUsername;
-        }
-        if (other.HasFillOauthScope) {
-          FillOauthScope = other.FillOauthScope;
-        }
-        this.MergeUnknownFields(other.UnknownFields);
-        return this;
-      }
-
-      public override Builder MergeFrom(pb::ICodedInputStream input) {
-        return MergeFrom(input, pb::ExtensionRegistry.Empty);
-      }
-
-      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
-        PrepareBuilder();
-        pb::UnknownFieldSet.Builder unknownFields = null;
-        uint tag;
-        string field_name;
-        while (input.ReadTag(out tag, out field_name)) {
-          if(tag == 0 && field_name != null) {
-            int field_ordinal = global::System.Array.BinarySearch(_simpleRequestFieldNames, field_name, global::System.StringComparer.Ordinal);
-            if(field_ordinal >= 0)
-              tag = _simpleRequestFieldTags[field_ordinal];
-            else {
-              if (unknownFields == null) {
-                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
-              }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
-              continue;
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while (input.ReadTag(out tag)) {
+        switch(tag) {
+          case 0:
+            throw pb::InvalidProtocolBufferException.InvalidTag();
+          default:
+            if (pb::WireFormat.IsEndGroupTag(tag)) {
+              return;
             }
+            break;
+          case 8: {
+            responseType_ = (global::Grpc.Testing.PayloadType) input.ReadEnum();
+            break;
           }
-          switch (tag) {
-            case 0: {
-              throw pb::InvalidProtocolBufferException.InvalidTag();
+          case 16: {
+            ResponseSize = input.ReadInt32();
+            break;
+          }
+          case 26: {
+            if (payload_ == null) {
+              payload_ = new global::Grpc.Testing.Payload();
             }
-            default: {
-              if (pb::WireFormat.IsEndGroupTag(tag)) {
-                if (unknownFields != null) {
-                  this.UnknownFields = unknownFields.Build();
-                }
-                return this;
-              }
-              if (unknownFields == null) {
-                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
-              }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
-              break;
-            }
-            case 8: {
-              object unknown;
-              if(input.ReadEnum(ref result.responseType_, out unknown)) {
-                result.hasResponseType = true;
-              } else if(unknown is int) {
-                if (unknownFields == null) {
-                  unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
-                }
-                unknownFields.MergeVarintField(1, (ulong)(int)unknown);
-              }
-              break;
-            }
-            case 16: {
-              result.hasResponseSize = input.ReadInt32(ref result.responseSize_);
-              break;
-            }
-            case 26: {
-              global::grpc.testing.Payload.Builder subBuilder = global::grpc.testing.Payload.CreateBuilder();
-              if (result.hasPayload) {
-                subBuilder.MergeFrom(Payload);
-              }
-              input.ReadMessage(subBuilder, extensionRegistry);
-              Payload = subBuilder.BuildPartial();
-              break;
-            }
-            case 32: {
-              result.hasFillUsername = input.ReadBool(ref result.fillUsername_);
-              break;
-            }
-            case 40: {
-              result.hasFillOauthScope = input.ReadBool(ref result.fillOauthScope_);
-              break;
-            }
+            input.ReadMessage(payload_);
+            break;
+          }
+          case 32: {
+            FillUsername = input.ReadBool();
+            break;
+          }
+          case 40: {
+            FillOauthScope = input.ReadBool();
+            break;
           }
         }
-
-        if (unknownFields != null) {
-          this.UnknownFields = unknownFields.Build();
-        }
-        return this;
-      }
-
-
-      public bool HasResponseType {
-       get { return result.hasResponseType; }
-      }
-      public global::grpc.testing.PayloadType ResponseType {
-        get { return result.ResponseType; }
-        set { SetResponseType(value); }
-      }
-      public Builder SetResponseType(global::grpc.testing.PayloadType value) {
-        PrepareBuilder();
-        result.hasResponseType = true;
-        result.responseType_ = value;
-        return this;
-      }
-      public Builder ClearResponseType() {
-        PrepareBuilder();
-        result.hasResponseType = false;
-        result.responseType_ = global::grpc.testing.PayloadType.COMPRESSABLE;
-        return this;
-      }
-
-      public bool HasResponseSize {
-        get { return result.hasResponseSize; }
-      }
-      public int ResponseSize {
-        get { return result.ResponseSize; }
-        set { SetResponseSize(value); }
-      }
-      public Builder SetResponseSize(int value) {
-        PrepareBuilder();
-        result.hasResponseSize = true;
-        result.responseSize_ = value;
-        return this;
-      }
-      public Builder ClearResponseSize() {
-        PrepareBuilder();
-        result.hasResponseSize = false;
-        result.responseSize_ = 0;
-        return this;
-      }
-
-      public bool HasPayload {
-       get { return result.hasPayload; }
-      }
-      public global::grpc.testing.Payload Payload {
-        get { return result.Payload; }
-        set { SetPayload(value); }
-      }
-      public Builder SetPayload(global::grpc.testing.Payload value) {
-        pb::ThrowHelper.ThrowIfNull(value, "value");
-        PrepareBuilder();
-        result.hasPayload = true;
-        result.payload_ = value;
-        return this;
-      }
-      public Builder SetPayload(global::grpc.testing.Payload.Builder builderForValue) {
-        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
-        PrepareBuilder();
-        result.hasPayload = true;
-        result.payload_ = builderForValue.Build();
-        return this;
-      }
-      public Builder MergePayload(global::grpc.testing.Payload value) {
-        pb::ThrowHelper.ThrowIfNull(value, "value");
-        PrepareBuilder();
-        if (result.hasPayload &&
-            result.payload_ != global::grpc.testing.Payload.DefaultInstance) {
-            result.payload_ = global::grpc.testing.Payload.CreateBuilder(result.payload_).MergeFrom(value).BuildPartial();
-        } else {
-          result.payload_ = value;
-        }
-        result.hasPayload = true;
-        return this;
-      }
-      public Builder ClearPayload() {
-        PrepareBuilder();
-        result.hasPayload = false;
-        result.payload_ = null;
-        return this;
-      }
-
-      public bool HasFillUsername {
-        get { return result.hasFillUsername; }
-      }
-      public bool FillUsername {
-        get { return result.FillUsername; }
-        set { SetFillUsername(value); }
-      }
-      public Builder SetFillUsername(bool value) {
-        PrepareBuilder();
-        result.hasFillUsername = true;
-        result.fillUsername_ = value;
-        return this;
-      }
-      public Builder ClearFillUsername() {
-        PrepareBuilder();
-        result.hasFillUsername = false;
-        result.fillUsername_ = false;
-        return this;
-      }
-
-      public bool HasFillOauthScope {
-        get { return result.hasFillOauthScope; }
-      }
-      public bool FillOauthScope {
-        get { return result.FillOauthScope; }
-        set { SetFillOauthScope(value); }
-      }
-      public Builder SetFillOauthScope(bool value) {
-        PrepareBuilder();
-        result.hasFillOauthScope = true;
-        result.fillOauthScope_ = value;
-        return this;
-      }
-      public Builder ClearFillOauthScope() {
-        PrepareBuilder();
-        result.hasFillOauthScope = false;
-        result.fillOauthScope_ = false;
-        return this;
       }
     }
-    static SimpleRequest() {
-      object.ReferenceEquals(global::grpc.testing.Messages.Descriptor, null);
-    }
+
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class SimpleResponse : pb::GeneratedMessage<SimpleResponse, SimpleResponse.Builder> {
-    private SimpleResponse() { }
-    private static readonly SimpleResponse defaultInstance = new SimpleResponse().MakeReadOnly();
-    private static readonly string[] _simpleResponseFieldNames = new string[] { "oauth_scope", "payload", "username" };
-    private static readonly uint[] _simpleResponseFieldTags = new uint[] { 26, 10, 18 };
-    public static SimpleResponse DefaultInstance {
-      get { return defaultInstance; }
+  public sealed partial class SimpleResponse : pb::IMessage<SimpleResponse> {
+    private static readonly pb::MessageParser<SimpleResponse> _parser = new pb::MessageParser<SimpleResponse>(() => new SimpleResponse());
+    public static pb::MessageParser<SimpleResponse> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.Messages.Descriptor.MessageTypes[2]; }
     }
 
-    public override SimpleResponse DefaultInstanceForType {
-      get { return DefaultInstance; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
-    protected override SimpleResponse ThisMessage {
-      get { return this; }
+    public SimpleResponse() {
+      OnConstruction();
     }
 
-    public static pbd::MessageDescriptor Descriptor {
-      get { return global::grpc.testing.Messages.internal__static_grpc_testing_SimpleResponse__Descriptor; }
+    partial void OnConstruction();
+
+    public SimpleResponse(SimpleResponse other) : this() {
+      Payload = other.payload_ != null ? other.Payload.Clone() : null;
+      username_ = other.username_;
+      oauthScope_ = other.oauthScope_;
     }
 
-    protected override pb::FieldAccess.FieldAccessorTable<SimpleResponse, SimpleResponse.Builder> InternalFieldAccessors {
-      get { return global::grpc.testing.Messages.internal__static_grpc_testing_SimpleResponse__FieldAccessorTable; }
+    public SimpleResponse Clone() {
+      return new SimpleResponse(this);
     }
 
     public const int PayloadFieldNumber = 1;
-    private bool hasPayload;
-    private global::grpc.testing.Payload payload_;
-    public bool HasPayload {
-      get { return hasPayload; }
-    }
-    public global::grpc.testing.Payload Payload {
-      get { return payload_ ?? global::grpc.testing.Payload.DefaultInstance; }
+    private global::Grpc.Testing.Payload payload_;
+    public global::Grpc.Testing.Payload Payload {
+      get { return payload_; }
+      set {
+        payload_ = value;
+      }
     }
 
     public const int UsernameFieldNumber = 2;
-    private bool hasUsername;
     private string username_ = "";
-    public bool HasUsername {
-      get { return hasUsername; }
-    }
     public string Username {
       get { return username_; }
+      set {
+        username_ = pb::Preconditions.CheckNotNull(value, "value");
+      }
     }
 
     public const int OauthScopeFieldNumber = 3;
-    private bool hasOauthScope;
     private string oauthScope_ = "";
-    public bool HasOauthScope {
-      get { return hasOauthScope; }
-    }
     public string OauthScope {
       get { return oauthScope_; }
+      set {
+        oauthScope_ = pb::Preconditions.CheckNotNull(value, "value");
+      }
     }
 
-    public override bool IsInitialized {
-      get {
+    public override bool Equals(object other) {
+      return Equals(other as SimpleResponse);
+    }
+
+    public bool Equals(SimpleResponse other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
         return true;
       }
+      if (!object.Equals(Payload, other.Payload)) return false;
+      if (Username != other.Username) return false;
+      if (OauthScope != other.OauthScope) return false;
+      return true;
     }
 
-    public override void WriteTo(pb::ICodedOutputStream output) {
-      int size = SerializedSize;
-      string[] field_names = _simpleResponseFieldNames;
-      if (hasPayload) {
-        output.WriteMessage(1, field_names[1], Payload);
-      }
-      if (hasUsername) {
-        output.WriteString(2, field_names[2], Username);
-      }
-      if (hasOauthScope) {
-        output.WriteString(3, field_names[0], OauthScope);
-      }
-      UnknownFields.WriteTo(output);
+    public override int GetHashCode() {
+      int hash = 1;
+      if (payload_ != null) hash ^= Payload.GetHashCode();
+      if (Username.Length != 0) hash ^= Username.GetHashCode();
+      if (OauthScope.Length != 0) hash ^= OauthScope.GetHashCode();
+      return hash;
     }
 
-    private int memoizedSerializedSize = -1;
-    public override int SerializedSize {
-      get {
-        int size = memoizedSerializedSize;
-        if (size != -1) return size;
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
 
-        size = 0;
-        if (hasPayload) {
-          size += pb::CodedOutputStream.ComputeMessageSize(1, Payload);
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (payload_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(Payload);
+      }
+      if (Username.Length != 0) {
+        output.WriteRawTag(18);
+        output.WriteString(Username);
+      }
+      if (OauthScope.Length != 0) {
+        output.WriteRawTag(26);
+        output.WriteString(OauthScope);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (payload_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload);
+      }
+      if (Username.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Username);
+      }
+      if (OauthScope.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(OauthScope);
+      }
+      return size;
+    }
+
+    public void MergeFrom(SimpleResponse other) {
+      if (other == null) {
+        return;
+      }
+      if (other.payload_ != null) {
+        if (payload_ == null) {
+          payload_ = new global::Grpc.Testing.Payload();
         }
-        if (hasUsername) {
-          size += pb::CodedOutputStream.ComputeStringSize(2, Username);
-        }
-        if (hasOauthScope) {
-          size += pb::CodedOutputStream.ComputeStringSize(3, OauthScope);
-        }
-        size += UnknownFields.SerializedSize;
-        memoizedSerializedSize = size;
-        return size;
+        Payload.MergeFrom(other.Payload);
+      }
+      if (other.Username.Length != 0) {
+        Username = other.Username;
+      }
+      if (other.OauthScope.Length != 0) {
+        OauthScope = other.OauthScope;
       }
     }
 
-    public static SimpleResponse ParseFrom(pb::ByteString data) {
-      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
-    }
-    public static SimpleResponse ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
-    }
-    public static SimpleResponse ParseFrom(byte[] data) {
-      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
-    }
-    public static SimpleResponse ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
-    }
-    public static SimpleResponse ParseFrom(global::System.IO.Stream input) {
-      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
-    }
-    public static SimpleResponse ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
-    }
-    public static SimpleResponse ParseDelimitedFrom(global::System.IO.Stream input) {
-      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
-    }
-    public static SimpleResponse ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
-      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
-    }
-    public static SimpleResponse ParseFrom(pb::ICodedInputStream input) {
-      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
-    }
-    public static SimpleResponse ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
-    }
-    private SimpleResponse MakeReadOnly() {
-      return this;
-    }
-
-    public static Builder CreateBuilder() { return new Builder(); }
-    public override Builder ToBuilder() { return CreateBuilder(this); }
-    public override Builder CreateBuilderForType() { return new Builder(); }
-    public static Builder CreateBuilder(SimpleResponse prototype) {
-      return new Builder(prototype);
-    }
-
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-    public sealed partial class Builder : pb::GeneratedBuilder<SimpleResponse, Builder> {
-      protected override Builder ThisBuilder {
-        get { return this; }
-      }
-      public Builder() {
-        result = DefaultInstance;
-        resultIsReadOnly = true;
-      }
-      internal Builder(SimpleResponse cloneFrom) {
-        result = cloneFrom;
-        resultIsReadOnly = true;
-      }
-
-      private bool resultIsReadOnly;
-      private SimpleResponse result;
-
-      private SimpleResponse PrepareBuilder() {
-        if (resultIsReadOnly) {
-          SimpleResponse original = result;
-          result = new SimpleResponse();
-          resultIsReadOnly = false;
-          MergeFrom(original);
-        }
-        return result;
-      }
-
-      public override bool IsInitialized {
-        get { return result.IsInitialized; }
-      }
-
-      protected override SimpleResponse MessageBeingBuilt {
-        get { return PrepareBuilder(); }
-      }
-
-      public override Builder Clear() {
-        result = DefaultInstance;
-        resultIsReadOnly = true;
-        return this;
-      }
-
-      public override Builder Clone() {
-        if (resultIsReadOnly) {
-          return new Builder(result);
-        } else {
-          return new Builder().MergeFrom(result);
-        }
-      }
-
-      public override pbd::MessageDescriptor DescriptorForType {
-        get { return global::grpc.testing.SimpleResponse.Descriptor; }
-      }
-
-      public override SimpleResponse DefaultInstanceForType {
-        get { return global::grpc.testing.SimpleResponse.DefaultInstance; }
-      }
-
-      public override SimpleResponse BuildPartial() {
-        if (resultIsReadOnly) {
-          return result;
-        }
-        resultIsReadOnly = true;
-        return result.MakeReadOnly();
-      }
-
-      public override Builder MergeFrom(pb::IMessage other) {
-        if (other is SimpleResponse) {
-          return MergeFrom((SimpleResponse) other);
-        } else {
-          base.MergeFrom(other);
-          return this;
-        }
-      }
-
-      public override Builder MergeFrom(SimpleResponse other) {
-        if (other == global::grpc.testing.SimpleResponse.DefaultInstance) return this;
-        PrepareBuilder();
-        if (other.HasPayload) {
-          MergePayload(other.Payload);
-        }
-        if (other.HasUsername) {
-          Username = other.Username;
-        }
-        if (other.HasOauthScope) {
-          OauthScope = other.OauthScope;
-        }
-        this.MergeUnknownFields(other.UnknownFields);
-        return this;
-      }
-
-      public override Builder MergeFrom(pb::ICodedInputStream input) {
-        return MergeFrom(input, pb::ExtensionRegistry.Empty);
-      }
-
-      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
-        PrepareBuilder();
-        pb::UnknownFieldSet.Builder unknownFields = null;
-        uint tag;
-        string field_name;
-        while (input.ReadTag(out tag, out field_name)) {
-          if(tag == 0 && field_name != null) {
-            int field_ordinal = global::System.Array.BinarySearch(_simpleResponseFieldNames, field_name, global::System.StringComparer.Ordinal);
-            if(field_ordinal >= 0)
-              tag = _simpleResponseFieldTags[field_ordinal];
-            else {
-              if (unknownFields == null) {
-                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
-              }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
-              continue;
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while (input.ReadTag(out tag)) {
+        switch(tag) {
+          case 0:
+            throw pb::InvalidProtocolBufferException.InvalidTag();
+          default:
+            if (pb::WireFormat.IsEndGroupTag(tag)) {
+              return;
             }
+            break;
+          case 10: {
+            if (payload_ == null) {
+              payload_ = new global::Grpc.Testing.Payload();
+            }
+            input.ReadMessage(payload_);
+            break;
           }
-          switch (tag) {
-            case 0: {
-              throw pb::InvalidProtocolBufferException.InvalidTag();
-            }
-            default: {
-              if (pb::WireFormat.IsEndGroupTag(tag)) {
-                if (unknownFields != null) {
-                  this.UnknownFields = unknownFields.Build();
-                }
-                return this;
-              }
-              if (unknownFields == null) {
-                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
-              }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
-              break;
-            }
-            case 10: {
-              global::grpc.testing.Payload.Builder subBuilder = global::grpc.testing.Payload.CreateBuilder();
-              if (result.hasPayload) {
-                subBuilder.MergeFrom(Payload);
-              }
-              input.ReadMessage(subBuilder, extensionRegistry);
-              Payload = subBuilder.BuildPartial();
-              break;
-            }
-            case 18: {
-              result.hasUsername = input.ReadString(ref result.username_);
-              break;
-            }
-            case 26: {
-              result.hasOauthScope = input.ReadString(ref result.oauthScope_);
-              break;
-            }
+          case 18: {
+            Username = input.ReadString();
+            break;
+          }
+          case 26: {
+            OauthScope = input.ReadString();
+            break;
           }
         }
-
-        if (unknownFields != null) {
-          this.UnknownFields = unknownFields.Build();
-        }
-        return this;
-      }
-
-
-      public bool HasPayload {
-       get { return result.hasPayload; }
-      }
-      public global::grpc.testing.Payload Payload {
-        get { return result.Payload; }
-        set { SetPayload(value); }
-      }
-      public Builder SetPayload(global::grpc.testing.Payload value) {
-        pb::ThrowHelper.ThrowIfNull(value, "value");
-        PrepareBuilder();
-        result.hasPayload = true;
-        result.payload_ = value;
-        return this;
-      }
-      public Builder SetPayload(global::grpc.testing.Payload.Builder builderForValue) {
-        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
-        PrepareBuilder();
-        result.hasPayload = true;
-        result.payload_ = builderForValue.Build();
-        return this;
-      }
-      public Builder MergePayload(global::grpc.testing.Payload value) {
-        pb::ThrowHelper.ThrowIfNull(value, "value");
-        PrepareBuilder();
-        if (result.hasPayload &&
-            result.payload_ != global::grpc.testing.Payload.DefaultInstance) {
-            result.payload_ = global::grpc.testing.Payload.CreateBuilder(result.payload_).MergeFrom(value).BuildPartial();
-        } else {
-          result.payload_ = value;
-        }
-        result.hasPayload = true;
-        return this;
-      }
-      public Builder ClearPayload() {
-        PrepareBuilder();
-        result.hasPayload = false;
-        result.payload_ = null;
-        return this;
-      }
-
-      public bool HasUsername {
-        get { return result.hasUsername; }
-      }
-      public string Username {
-        get { return result.Username; }
-        set { SetUsername(value); }
-      }
-      public Builder SetUsername(string value) {
-        pb::ThrowHelper.ThrowIfNull(value, "value");
-        PrepareBuilder();
-        result.hasUsername = true;
-        result.username_ = value;
-        return this;
-      }
-      public Builder ClearUsername() {
-        PrepareBuilder();
-        result.hasUsername = false;
-        result.username_ = "";
-        return this;
-      }
-
-      public bool HasOauthScope {
-        get { return result.hasOauthScope; }
-      }
-      public string OauthScope {
-        get { return result.OauthScope; }
-        set { SetOauthScope(value); }
-      }
-      public Builder SetOauthScope(string value) {
-        pb::ThrowHelper.ThrowIfNull(value, "value");
-        PrepareBuilder();
-        result.hasOauthScope = true;
-        result.oauthScope_ = value;
-        return this;
-      }
-      public Builder ClearOauthScope() {
-        PrepareBuilder();
-        result.hasOauthScope = false;
-        result.oauthScope_ = "";
-        return this;
       }
     }
-    static SimpleResponse() {
-      object.ReferenceEquals(global::grpc.testing.Messages.Descriptor, null);
-    }
+
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class StreamingInputCallRequest : pb::GeneratedMessage<StreamingInputCallRequest, StreamingInputCallRequest.Builder> {
-    private StreamingInputCallRequest() { }
-    private static readonly StreamingInputCallRequest defaultInstance = new StreamingInputCallRequest().MakeReadOnly();
-    private static readonly string[] _streamingInputCallRequestFieldNames = new string[] { "payload" };
-    private static readonly uint[] _streamingInputCallRequestFieldTags = new uint[] { 10 };
-    public static StreamingInputCallRequest DefaultInstance {
-      get { return defaultInstance; }
+  public sealed partial class StreamingInputCallRequest : pb::IMessage<StreamingInputCallRequest> {
+    private static readonly pb::MessageParser<StreamingInputCallRequest> _parser = new pb::MessageParser<StreamingInputCallRequest>(() => new StreamingInputCallRequest());
+    public static pb::MessageParser<StreamingInputCallRequest> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.Messages.Descriptor.MessageTypes[3]; }
     }
 
-    public override StreamingInputCallRequest DefaultInstanceForType {
-      get { return DefaultInstance; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
-    protected override StreamingInputCallRequest ThisMessage {
-      get { return this; }
+    public StreamingInputCallRequest() {
+      OnConstruction();
     }
 
-    public static pbd::MessageDescriptor Descriptor {
-      get { return global::grpc.testing.Messages.internal__static_grpc_testing_StreamingInputCallRequest__Descriptor; }
+    partial void OnConstruction();
+
+    public StreamingInputCallRequest(StreamingInputCallRequest other) : this() {
+      Payload = other.payload_ != null ? other.Payload.Clone() : null;
     }
 
-    protected override pb::FieldAccess.FieldAccessorTable<StreamingInputCallRequest, StreamingInputCallRequest.Builder> InternalFieldAccessors {
-      get { return global::grpc.testing.Messages.internal__static_grpc_testing_StreamingInputCallRequest__FieldAccessorTable; }
+    public StreamingInputCallRequest Clone() {
+      return new StreamingInputCallRequest(this);
     }
 
     public const int PayloadFieldNumber = 1;
-    private bool hasPayload;
-    private global::grpc.testing.Payload payload_;
-    public bool HasPayload {
-      get { return hasPayload; }
-    }
-    public global::grpc.testing.Payload Payload {
-      get { return payload_ ?? global::grpc.testing.Payload.DefaultInstance; }
+    private global::Grpc.Testing.Payload payload_;
+    public global::Grpc.Testing.Payload Payload {
+      get { return payload_; }
+      set {
+        payload_ = value;
+      }
     }
 
-    public override bool IsInitialized {
-      get {
+    public override bool Equals(object other) {
+      return Equals(other as StreamingInputCallRequest);
+    }
+
+    public bool Equals(StreamingInputCallRequest other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
         return true;
       }
+      if (!object.Equals(Payload, other.Payload)) return false;
+      return true;
     }
 
-    public override void WriteTo(pb::ICodedOutputStream output) {
-      int size = SerializedSize;
-      string[] field_names = _streamingInputCallRequestFieldNames;
-      if (hasPayload) {
-        output.WriteMessage(1, field_names[0], Payload);
+    public override int GetHashCode() {
+      int hash = 1;
+      if (payload_ != null) hash ^= Payload.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (payload_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(Payload);
       }
-      UnknownFields.WriteTo(output);
     }
 
-    private int memoizedSerializedSize = -1;
-    public override int SerializedSize {
-      get {
-        int size = memoizedSerializedSize;
-        if (size != -1) return size;
+    public int CalculateSize() {
+      int size = 0;
+      if (payload_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload);
+      }
+      return size;
+    }
 
-        size = 0;
-        if (hasPayload) {
-          size += pb::CodedOutputStream.ComputeMessageSize(1, Payload);
+    public void MergeFrom(StreamingInputCallRequest other) {
+      if (other == null) {
+        return;
+      }
+      if (other.payload_ != null) {
+        if (payload_ == null) {
+          payload_ = new global::Grpc.Testing.Payload();
         }
-        size += UnknownFields.SerializedSize;
-        memoizedSerializedSize = size;
-        return size;
+        Payload.MergeFrom(other.Payload);
       }
     }
 
-    public static StreamingInputCallRequest ParseFrom(pb::ByteString data) {
-      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
-    }
-    public static StreamingInputCallRequest ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
-    }
-    public static StreamingInputCallRequest ParseFrom(byte[] data) {
-      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
-    }
-    public static StreamingInputCallRequest ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
-    }
-    public static StreamingInputCallRequest ParseFrom(global::System.IO.Stream input) {
-      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
-    }
-    public static StreamingInputCallRequest ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
-    }
-    public static StreamingInputCallRequest ParseDelimitedFrom(global::System.IO.Stream input) {
-      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
-    }
-    public static StreamingInputCallRequest ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
-      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
-    }
-    public static StreamingInputCallRequest ParseFrom(pb::ICodedInputStream input) {
-      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
-    }
-    public static StreamingInputCallRequest ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
-    }
-    private StreamingInputCallRequest MakeReadOnly() {
-      return this;
-    }
-
-    public static Builder CreateBuilder() { return new Builder(); }
-    public override Builder ToBuilder() { return CreateBuilder(this); }
-    public override Builder CreateBuilderForType() { return new Builder(); }
-    public static Builder CreateBuilder(StreamingInputCallRequest prototype) {
-      return new Builder(prototype);
-    }
-
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-    public sealed partial class Builder : pb::GeneratedBuilder<StreamingInputCallRequest, Builder> {
-      protected override Builder ThisBuilder {
-        get { return this; }
-      }
-      public Builder() {
-        result = DefaultInstance;
-        resultIsReadOnly = true;
-      }
-      internal Builder(StreamingInputCallRequest cloneFrom) {
-        result = cloneFrom;
-        resultIsReadOnly = true;
-      }
-
-      private bool resultIsReadOnly;
-      private StreamingInputCallRequest result;
-
-      private StreamingInputCallRequest PrepareBuilder() {
-        if (resultIsReadOnly) {
-          StreamingInputCallRequest original = result;
-          result = new StreamingInputCallRequest();
-          resultIsReadOnly = false;
-          MergeFrom(original);
-        }
-        return result;
-      }
-
-      public override bool IsInitialized {
-        get { return result.IsInitialized; }
-      }
-
-      protected override StreamingInputCallRequest MessageBeingBuilt {
-        get { return PrepareBuilder(); }
-      }
-
-      public override Builder Clear() {
-        result = DefaultInstance;
-        resultIsReadOnly = true;
-        return this;
-      }
-
-      public override Builder Clone() {
-        if (resultIsReadOnly) {
-          return new Builder(result);
-        } else {
-          return new Builder().MergeFrom(result);
-        }
-      }
-
-      public override pbd::MessageDescriptor DescriptorForType {
-        get { return global::grpc.testing.StreamingInputCallRequest.Descriptor; }
-      }
-
-      public override StreamingInputCallRequest DefaultInstanceForType {
-        get { return global::grpc.testing.StreamingInputCallRequest.DefaultInstance; }
-      }
-
-      public override StreamingInputCallRequest BuildPartial() {
-        if (resultIsReadOnly) {
-          return result;
-        }
-        resultIsReadOnly = true;
-        return result.MakeReadOnly();
-      }
-
-      public override Builder MergeFrom(pb::IMessage other) {
-        if (other is StreamingInputCallRequest) {
-          return MergeFrom((StreamingInputCallRequest) other);
-        } else {
-          base.MergeFrom(other);
-          return this;
-        }
-      }
-
-      public override Builder MergeFrom(StreamingInputCallRequest other) {
-        if (other == global::grpc.testing.StreamingInputCallRequest.DefaultInstance) return this;
-        PrepareBuilder();
-        if (other.HasPayload) {
-          MergePayload(other.Payload);
-        }
-        this.MergeUnknownFields(other.UnknownFields);
-        return this;
-      }
-
-      public override Builder MergeFrom(pb::ICodedInputStream input) {
-        return MergeFrom(input, pb::ExtensionRegistry.Empty);
-      }
-
-      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
-        PrepareBuilder();
-        pb::UnknownFieldSet.Builder unknownFields = null;
-        uint tag;
-        string field_name;
-        while (input.ReadTag(out tag, out field_name)) {
-          if(tag == 0 && field_name != null) {
-            int field_ordinal = global::System.Array.BinarySearch(_streamingInputCallRequestFieldNames, field_name, global::System.StringComparer.Ordinal);
-            if(field_ordinal >= 0)
-              tag = _streamingInputCallRequestFieldTags[field_ordinal];
-            else {
-              if (unknownFields == null) {
-                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
-              }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
-              continue;
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while (input.ReadTag(out tag)) {
+        switch(tag) {
+          case 0:
+            throw pb::InvalidProtocolBufferException.InvalidTag();
+          default:
+            if (pb::WireFormat.IsEndGroupTag(tag)) {
+              return;
             }
-          }
-          switch (tag) {
-            case 0: {
-              throw pb::InvalidProtocolBufferException.InvalidTag();
+            break;
+          case 10: {
+            if (payload_ == null) {
+              payload_ = new global::Grpc.Testing.Payload();
             }
-            default: {
-              if (pb::WireFormat.IsEndGroupTag(tag)) {
-                if (unknownFields != null) {
-                  this.UnknownFields = unknownFields.Build();
-                }
-                return this;
-              }
-              if (unknownFields == null) {
-                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
-              }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
-              break;
-            }
-            case 10: {
-              global::grpc.testing.Payload.Builder subBuilder = global::grpc.testing.Payload.CreateBuilder();
-              if (result.hasPayload) {
-                subBuilder.MergeFrom(Payload);
-              }
-              input.ReadMessage(subBuilder, extensionRegistry);
-              Payload = subBuilder.BuildPartial();
-              break;
-            }
+            input.ReadMessage(payload_);
+            break;
           }
         }
-
-        if (unknownFields != null) {
-          this.UnknownFields = unknownFields.Build();
-        }
-        return this;
-      }
-
-
-      public bool HasPayload {
-       get { return result.hasPayload; }
-      }
-      public global::grpc.testing.Payload Payload {
-        get { return result.Payload; }
-        set { SetPayload(value); }
-      }
-      public Builder SetPayload(global::grpc.testing.Payload value) {
-        pb::ThrowHelper.ThrowIfNull(value, "value");
-        PrepareBuilder();
-        result.hasPayload = true;
-        result.payload_ = value;
-        return this;
-      }
-      public Builder SetPayload(global::grpc.testing.Payload.Builder builderForValue) {
-        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
-        PrepareBuilder();
-        result.hasPayload = true;
-        result.payload_ = builderForValue.Build();
-        return this;
-      }
-      public Builder MergePayload(global::grpc.testing.Payload value) {
-        pb::ThrowHelper.ThrowIfNull(value, "value");
-        PrepareBuilder();
-        if (result.hasPayload &&
-            result.payload_ != global::grpc.testing.Payload.DefaultInstance) {
-            result.payload_ = global::grpc.testing.Payload.CreateBuilder(result.payload_).MergeFrom(value).BuildPartial();
-        } else {
-          result.payload_ = value;
-        }
-        result.hasPayload = true;
-        return this;
-      }
-      public Builder ClearPayload() {
-        PrepareBuilder();
-        result.hasPayload = false;
-        result.payload_ = null;
-        return this;
       }
     }
-    static StreamingInputCallRequest() {
-      object.ReferenceEquals(global::grpc.testing.Messages.Descriptor, null);
-    }
+
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class StreamingInputCallResponse : pb::GeneratedMessage<StreamingInputCallResponse, StreamingInputCallResponse.Builder> {
-    private StreamingInputCallResponse() { }
-    private static readonly StreamingInputCallResponse defaultInstance = new StreamingInputCallResponse().MakeReadOnly();
-    private static readonly string[] _streamingInputCallResponseFieldNames = new string[] { "aggregated_payload_size" };
-    private static readonly uint[] _streamingInputCallResponseFieldTags = new uint[] { 8 };
-    public static StreamingInputCallResponse DefaultInstance {
-      get { return defaultInstance; }
+  public sealed partial class StreamingInputCallResponse : pb::IMessage<StreamingInputCallResponse> {
+    private static readonly pb::MessageParser<StreamingInputCallResponse> _parser = new pb::MessageParser<StreamingInputCallResponse>(() => new StreamingInputCallResponse());
+    public static pb::MessageParser<StreamingInputCallResponse> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.Messages.Descriptor.MessageTypes[4]; }
     }
 
-    public override StreamingInputCallResponse DefaultInstanceForType {
-      get { return DefaultInstance; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
-    protected override StreamingInputCallResponse ThisMessage {
-      get { return this; }
+    public StreamingInputCallResponse() {
+      OnConstruction();
     }
 
-    public static pbd::MessageDescriptor Descriptor {
-      get { return global::grpc.testing.Messages.internal__static_grpc_testing_StreamingInputCallResponse__Descriptor; }
+    partial void OnConstruction();
+
+    public StreamingInputCallResponse(StreamingInputCallResponse other) : this() {
+      aggregatedPayloadSize_ = other.aggregatedPayloadSize_;
     }
 
-    protected override pb::FieldAccess.FieldAccessorTable<StreamingInputCallResponse, StreamingInputCallResponse.Builder> InternalFieldAccessors {
-      get { return global::grpc.testing.Messages.internal__static_grpc_testing_StreamingInputCallResponse__FieldAccessorTable; }
+    public StreamingInputCallResponse Clone() {
+      return new StreamingInputCallResponse(this);
     }
 
     public const int AggregatedPayloadSizeFieldNumber = 1;
-    private bool hasAggregatedPayloadSize;
     private int aggregatedPayloadSize_;
-    public bool HasAggregatedPayloadSize {
-      get { return hasAggregatedPayloadSize; }
-    }
     public int AggregatedPayloadSize {
       get { return aggregatedPayloadSize_; }
+      set {
+        aggregatedPayloadSize_ = value;
+      }
     }
 
-    public override bool IsInitialized {
-      get {
+    public override bool Equals(object other) {
+      return Equals(other as StreamingInputCallResponse);
+    }
+
+    public bool Equals(StreamingInputCallResponse other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
         return true;
       }
+      if (AggregatedPayloadSize != other.AggregatedPayloadSize) return false;
+      return true;
     }
 
-    public override void WriteTo(pb::ICodedOutputStream output) {
-      int size = SerializedSize;
-      string[] field_names = _streamingInputCallResponseFieldNames;
-      if (hasAggregatedPayloadSize) {
-        output.WriteInt32(1, field_names[0], AggregatedPayloadSize);
-      }
-      UnknownFields.WriteTo(output);
+    public override int GetHashCode() {
+      int hash = 1;
+      if (AggregatedPayloadSize != 0) hash ^= AggregatedPayloadSize.GetHashCode();
+      return hash;
     }
 
-    private int memoizedSerializedSize = -1;
-    public override int SerializedSize {
-      get {
-        int size = memoizedSerializedSize;
-        if (size != -1) return size;
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
 
-        size = 0;
-        if (hasAggregatedPayloadSize) {
-          size += pb::CodedOutputStream.ComputeInt32Size(1, AggregatedPayloadSize);
-        }
-        size += UnknownFields.SerializedSize;
-        memoizedSerializedSize = size;
-        return size;
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (AggregatedPayloadSize != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(AggregatedPayloadSize);
       }
     }
 
-    public static StreamingInputCallResponse ParseFrom(pb::ByteString data) {
-      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
-    }
-    public static StreamingInputCallResponse ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
-    }
-    public static StreamingInputCallResponse ParseFrom(byte[] data) {
-      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
-    }
-    public static StreamingInputCallResponse ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
-    }
-    public static StreamingInputCallResponse ParseFrom(global::System.IO.Stream input) {
-      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
-    }
-    public static StreamingInputCallResponse ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
-    }
-    public static StreamingInputCallResponse ParseDelimitedFrom(global::System.IO.Stream input) {
-      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
-    }
-    public static StreamingInputCallResponse ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
-      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
-    }
-    public static StreamingInputCallResponse ParseFrom(pb::ICodedInputStream input) {
-      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
-    }
-    public static StreamingInputCallResponse ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
-    }
-    private StreamingInputCallResponse MakeReadOnly() {
-      return this;
+    public int CalculateSize() {
+      int size = 0;
+      if (AggregatedPayloadSize != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(AggregatedPayloadSize);
+      }
+      return size;
     }
 
-    public static Builder CreateBuilder() { return new Builder(); }
-    public override Builder ToBuilder() { return CreateBuilder(this); }
-    public override Builder CreateBuilderForType() { return new Builder(); }
-    public static Builder CreateBuilder(StreamingInputCallResponse prototype) {
-      return new Builder(prototype);
+    public void MergeFrom(StreamingInputCallResponse other) {
+      if (other == null) {
+        return;
+      }
+      if (other.AggregatedPayloadSize != 0) {
+        AggregatedPayloadSize = other.AggregatedPayloadSize;
+      }
     }
 
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-    public sealed partial class Builder : pb::GeneratedBuilder<StreamingInputCallResponse, Builder> {
-      protected override Builder ThisBuilder {
-        get { return this; }
-      }
-      public Builder() {
-        result = DefaultInstance;
-        resultIsReadOnly = true;
-      }
-      internal Builder(StreamingInputCallResponse cloneFrom) {
-        result = cloneFrom;
-        resultIsReadOnly = true;
-      }
-
-      private bool resultIsReadOnly;
-      private StreamingInputCallResponse result;
-
-      private StreamingInputCallResponse PrepareBuilder() {
-        if (resultIsReadOnly) {
-          StreamingInputCallResponse original = result;
-          result = new StreamingInputCallResponse();
-          resultIsReadOnly = false;
-          MergeFrom(original);
-        }
-        return result;
-      }
-
-      public override bool IsInitialized {
-        get { return result.IsInitialized; }
-      }
-
-      protected override StreamingInputCallResponse MessageBeingBuilt {
-        get { return PrepareBuilder(); }
-      }
-
-      public override Builder Clear() {
-        result = DefaultInstance;
-        resultIsReadOnly = true;
-        return this;
-      }
-
-      public override Builder Clone() {
-        if (resultIsReadOnly) {
-          return new Builder(result);
-        } else {
-          return new Builder().MergeFrom(result);
-        }
-      }
-
-      public override pbd::MessageDescriptor DescriptorForType {
-        get { return global::grpc.testing.StreamingInputCallResponse.Descriptor; }
-      }
-
-      public override StreamingInputCallResponse DefaultInstanceForType {
-        get { return global::grpc.testing.StreamingInputCallResponse.DefaultInstance; }
-      }
-
-      public override StreamingInputCallResponse BuildPartial() {
-        if (resultIsReadOnly) {
-          return result;
-        }
-        resultIsReadOnly = true;
-        return result.MakeReadOnly();
-      }
-
-      public override Builder MergeFrom(pb::IMessage other) {
-        if (other is StreamingInputCallResponse) {
-          return MergeFrom((StreamingInputCallResponse) other);
-        } else {
-          base.MergeFrom(other);
-          return this;
-        }
-      }
-
-      public override Builder MergeFrom(StreamingInputCallResponse other) {
-        if (other == global::grpc.testing.StreamingInputCallResponse.DefaultInstance) return this;
-        PrepareBuilder();
-        if (other.HasAggregatedPayloadSize) {
-          AggregatedPayloadSize = other.AggregatedPayloadSize;
-        }
-        this.MergeUnknownFields(other.UnknownFields);
-        return this;
-      }
-
-      public override Builder MergeFrom(pb::ICodedInputStream input) {
-        return MergeFrom(input, pb::ExtensionRegistry.Empty);
-      }
-
-      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
-        PrepareBuilder();
-        pb::UnknownFieldSet.Builder unknownFields = null;
-        uint tag;
-        string field_name;
-        while (input.ReadTag(out tag, out field_name)) {
-          if(tag == 0 && field_name != null) {
-            int field_ordinal = global::System.Array.BinarySearch(_streamingInputCallResponseFieldNames, field_name, global::System.StringComparer.Ordinal);
-            if(field_ordinal >= 0)
-              tag = _streamingInputCallResponseFieldTags[field_ordinal];
-            else {
-              if (unknownFields == null) {
-                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
-              }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
-              continue;
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while (input.ReadTag(out tag)) {
+        switch(tag) {
+          case 0:
+            throw pb::InvalidProtocolBufferException.InvalidTag();
+          default:
+            if (pb::WireFormat.IsEndGroupTag(tag)) {
+              return;
             }
-          }
-          switch (tag) {
-            case 0: {
-              throw pb::InvalidProtocolBufferException.InvalidTag();
-            }
-            default: {
-              if (pb::WireFormat.IsEndGroupTag(tag)) {
-                if (unknownFields != null) {
-                  this.UnknownFields = unknownFields.Build();
-                }
-                return this;
-              }
-              if (unknownFields == null) {
-                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
-              }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
-              break;
-            }
-            case 8: {
-              result.hasAggregatedPayloadSize = input.ReadInt32(ref result.aggregatedPayloadSize_);
-              break;
-            }
+            break;
+          case 8: {
+            AggregatedPayloadSize = input.ReadInt32();
+            break;
           }
         }
-
-        if (unknownFields != null) {
-          this.UnknownFields = unknownFields.Build();
-        }
-        return this;
-      }
-
-
-      public bool HasAggregatedPayloadSize {
-        get { return result.hasAggregatedPayloadSize; }
-      }
-      public int AggregatedPayloadSize {
-        get { return result.AggregatedPayloadSize; }
-        set { SetAggregatedPayloadSize(value); }
-      }
-      public Builder SetAggregatedPayloadSize(int value) {
-        PrepareBuilder();
-        result.hasAggregatedPayloadSize = true;
-        result.aggregatedPayloadSize_ = value;
-        return this;
-      }
-      public Builder ClearAggregatedPayloadSize() {
-        PrepareBuilder();
-        result.hasAggregatedPayloadSize = false;
-        result.aggregatedPayloadSize_ = 0;
-        return this;
       }
     }
-    static StreamingInputCallResponse() {
-      object.ReferenceEquals(global::grpc.testing.Messages.Descriptor, null);
-    }
+
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class ResponseParameters : pb::GeneratedMessage<ResponseParameters, ResponseParameters.Builder> {
-    private ResponseParameters() { }
-    private static readonly ResponseParameters defaultInstance = new ResponseParameters().MakeReadOnly();
-    private static readonly string[] _responseParametersFieldNames = new string[] { "interval_us", "size" };
-    private static readonly uint[] _responseParametersFieldTags = new uint[] { 16, 8 };
-    public static ResponseParameters DefaultInstance {
-      get { return defaultInstance; }
+  public sealed partial class ResponseParameters : pb::IMessage<ResponseParameters> {
+    private static readonly pb::MessageParser<ResponseParameters> _parser = new pb::MessageParser<ResponseParameters>(() => new ResponseParameters());
+    public static pb::MessageParser<ResponseParameters> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.Messages.Descriptor.MessageTypes[5]; }
     }
 
-    public override ResponseParameters DefaultInstanceForType {
-      get { return DefaultInstance; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
-    protected override ResponseParameters ThisMessage {
-      get { return this; }
+    public ResponseParameters() {
+      OnConstruction();
     }
 
-    public static pbd::MessageDescriptor Descriptor {
-      get { return global::grpc.testing.Messages.internal__static_grpc_testing_ResponseParameters__Descriptor; }
+    partial void OnConstruction();
+
+    public ResponseParameters(ResponseParameters other) : this() {
+      size_ = other.size_;
+      intervalUs_ = other.intervalUs_;
     }
 
-    protected override pb::FieldAccess.FieldAccessorTable<ResponseParameters, ResponseParameters.Builder> InternalFieldAccessors {
-      get { return global::grpc.testing.Messages.internal__static_grpc_testing_ResponseParameters__FieldAccessorTable; }
+    public ResponseParameters Clone() {
+      return new ResponseParameters(this);
     }
 
     public const int SizeFieldNumber = 1;
-    private bool hasSize;
     private int size_;
-    public bool HasSize {
-      get { return hasSize; }
-    }
     public int Size {
       get { return size_; }
+      set {
+        size_ = value;
+      }
     }
 
     public const int IntervalUsFieldNumber = 2;
-    private bool hasIntervalUs;
     private int intervalUs_;
-    public bool HasIntervalUs {
-      get { return hasIntervalUs; }
-    }
     public int IntervalUs {
       get { return intervalUs_; }
+      set {
+        intervalUs_ = value;
+      }
     }
 
-    public override bool IsInitialized {
-      get {
+    public override bool Equals(object other) {
+      return Equals(other as ResponseParameters);
+    }
+
+    public bool Equals(ResponseParameters other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
         return true;
       }
+      if (Size != other.Size) return false;
+      if (IntervalUs != other.IntervalUs) return false;
+      return true;
     }
 
-    public override void WriteTo(pb::ICodedOutputStream output) {
-      int size = SerializedSize;
-      string[] field_names = _responseParametersFieldNames;
-      if (hasSize) {
-        output.WriteInt32(1, field_names[1], Size);
-      }
-      if (hasIntervalUs) {
-        output.WriteInt32(2, field_names[0], IntervalUs);
-      }
-      UnknownFields.WriteTo(output);
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Size != 0) hash ^= Size.GetHashCode();
+      if (IntervalUs != 0) hash ^= IntervalUs.GetHashCode();
+      return hash;
     }
 
-    private int memoizedSerializedSize = -1;
-    public override int SerializedSize {
-      get {
-        int size = memoizedSerializedSize;
-        if (size != -1) return size;
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
 
-        size = 0;
-        if (hasSize) {
-          size += pb::CodedOutputStream.ComputeInt32Size(1, Size);
-        }
-        if (hasIntervalUs) {
-          size += pb::CodedOutputStream.ComputeInt32Size(2, IntervalUs);
-        }
-        size += UnknownFields.SerializedSize;
-        memoizedSerializedSize = size;
-        return size;
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Size != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(Size);
+      }
+      if (IntervalUs != 0) {
+        output.WriteRawTag(16);
+        output.WriteInt32(IntervalUs);
       }
     }
 
-    public static ResponseParameters ParseFrom(pb::ByteString data) {
-      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
-    }
-    public static ResponseParameters ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
-    }
-    public static ResponseParameters ParseFrom(byte[] data) {
-      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
-    }
-    public static ResponseParameters ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
-    }
-    public static ResponseParameters ParseFrom(global::System.IO.Stream input) {
-      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
-    }
-    public static ResponseParameters ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
-    }
-    public static ResponseParameters ParseDelimitedFrom(global::System.IO.Stream input) {
-      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
-    }
-    public static ResponseParameters ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
-      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
-    }
-    public static ResponseParameters ParseFrom(pb::ICodedInputStream input) {
-      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
-    }
-    public static ResponseParameters ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
-    }
-    private ResponseParameters MakeReadOnly() {
-      return this;
+    public int CalculateSize() {
+      int size = 0;
+      if (Size != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Size);
+      }
+      if (IntervalUs != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(IntervalUs);
+      }
+      return size;
     }
 
-    public static Builder CreateBuilder() { return new Builder(); }
-    public override Builder ToBuilder() { return CreateBuilder(this); }
-    public override Builder CreateBuilderForType() { return new Builder(); }
-    public static Builder CreateBuilder(ResponseParameters prototype) {
-      return new Builder(prototype);
+    public void MergeFrom(ResponseParameters other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Size != 0) {
+        Size = other.Size;
+      }
+      if (other.IntervalUs != 0) {
+        IntervalUs = other.IntervalUs;
+      }
     }
 
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-    public sealed partial class Builder : pb::GeneratedBuilder<ResponseParameters, Builder> {
-      protected override Builder ThisBuilder {
-        get { return this; }
-      }
-      public Builder() {
-        result = DefaultInstance;
-        resultIsReadOnly = true;
-      }
-      internal Builder(ResponseParameters cloneFrom) {
-        result = cloneFrom;
-        resultIsReadOnly = true;
-      }
-
-      private bool resultIsReadOnly;
-      private ResponseParameters result;
-
-      private ResponseParameters PrepareBuilder() {
-        if (resultIsReadOnly) {
-          ResponseParameters original = result;
-          result = new ResponseParameters();
-          resultIsReadOnly = false;
-          MergeFrom(original);
-        }
-        return result;
-      }
-
-      public override bool IsInitialized {
-        get { return result.IsInitialized; }
-      }
-
-      protected override ResponseParameters MessageBeingBuilt {
-        get { return PrepareBuilder(); }
-      }
-
-      public override Builder Clear() {
-        result = DefaultInstance;
-        resultIsReadOnly = true;
-        return this;
-      }
-
-      public override Builder Clone() {
-        if (resultIsReadOnly) {
-          return new Builder(result);
-        } else {
-          return new Builder().MergeFrom(result);
-        }
-      }
-
-      public override pbd::MessageDescriptor DescriptorForType {
-        get { return global::grpc.testing.ResponseParameters.Descriptor; }
-      }
-
-      public override ResponseParameters DefaultInstanceForType {
-        get { return global::grpc.testing.ResponseParameters.DefaultInstance; }
-      }
-
-      public override ResponseParameters BuildPartial() {
-        if (resultIsReadOnly) {
-          return result;
-        }
-        resultIsReadOnly = true;
-        return result.MakeReadOnly();
-      }
-
-      public override Builder MergeFrom(pb::IMessage other) {
-        if (other is ResponseParameters) {
-          return MergeFrom((ResponseParameters) other);
-        } else {
-          base.MergeFrom(other);
-          return this;
-        }
-      }
-
-      public override Builder MergeFrom(ResponseParameters other) {
-        if (other == global::grpc.testing.ResponseParameters.DefaultInstance) return this;
-        PrepareBuilder();
-        if (other.HasSize) {
-          Size = other.Size;
-        }
-        if (other.HasIntervalUs) {
-          IntervalUs = other.IntervalUs;
-        }
-        this.MergeUnknownFields(other.UnknownFields);
-        return this;
-      }
-
-      public override Builder MergeFrom(pb::ICodedInputStream input) {
-        return MergeFrom(input, pb::ExtensionRegistry.Empty);
-      }
-
-      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
-        PrepareBuilder();
-        pb::UnknownFieldSet.Builder unknownFields = null;
-        uint tag;
-        string field_name;
-        while (input.ReadTag(out tag, out field_name)) {
-          if(tag == 0 && field_name != null) {
-            int field_ordinal = global::System.Array.BinarySearch(_responseParametersFieldNames, field_name, global::System.StringComparer.Ordinal);
-            if(field_ordinal >= 0)
-              tag = _responseParametersFieldTags[field_ordinal];
-            else {
-              if (unknownFields == null) {
-                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
-              }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
-              continue;
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while (input.ReadTag(out tag)) {
+        switch(tag) {
+          case 0:
+            throw pb::InvalidProtocolBufferException.InvalidTag();
+          default:
+            if (pb::WireFormat.IsEndGroupTag(tag)) {
+              return;
             }
+            break;
+          case 8: {
+            Size = input.ReadInt32();
+            break;
           }
-          switch (tag) {
-            case 0: {
-              throw pb::InvalidProtocolBufferException.InvalidTag();
-            }
-            default: {
-              if (pb::WireFormat.IsEndGroupTag(tag)) {
-                if (unknownFields != null) {
-                  this.UnknownFields = unknownFields.Build();
-                }
-                return this;
-              }
-              if (unknownFields == null) {
-                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
-              }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
-              break;
-            }
-            case 8: {
-              result.hasSize = input.ReadInt32(ref result.size_);
-              break;
-            }
-            case 16: {
-              result.hasIntervalUs = input.ReadInt32(ref result.intervalUs_);
-              break;
-            }
+          case 16: {
+            IntervalUs = input.ReadInt32();
+            break;
           }
         }
-
-        if (unknownFields != null) {
-          this.UnknownFields = unknownFields.Build();
-        }
-        return this;
-      }
-
-
-      public bool HasSize {
-        get { return result.hasSize; }
-      }
-      public int Size {
-        get { return result.Size; }
-        set { SetSize(value); }
-      }
-      public Builder SetSize(int value) {
-        PrepareBuilder();
-        result.hasSize = true;
-        result.size_ = value;
-        return this;
-      }
-      public Builder ClearSize() {
-        PrepareBuilder();
-        result.hasSize = false;
-        result.size_ = 0;
-        return this;
-      }
-
-      public bool HasIntervalUs {
-        get { return result.hasIntervalUs; }
-      }
-      public int IntervalUs {
-        get { return result.IntervalUs; }
-        set { SetIntervalUs(value); }
-      }
-      public Builder SetIntervalUs(int value) {
-        PrepareBuilder();
-        result.hasIntervalUs = true;
-        result.intervalUs_ = value;
-        return this;
-      }
-      public Builder ClearIntervalUs() {
-        PrepareBuilder();
-        result.hasIntervalUs = false;
-        result.intervalUs_ = 0;
-        return this;
       }
     }
-    static ResponseParameters() {
-      object.ReferenceEquals(global::grpc.testing.Messages.Descriptor, null);
-    }
+
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class StreamingOutputCallRequest : pb::GeneratedMessage<StreamingOutputCallRequest, StreamingOutputCallRequest.Builder> {
-    private StreamingOutputCallRequest() { }
-    private static readonly StreamingOutputCallRequest defaultInstance = new StreamingOutputCallRequest().MakeReadOnly();
-    private static readonly string[] _streamingOutputCallRequestFieldNames = new string[] { "payload", "response_parameters", "response_type" };
-    private static readonly uint[] _streamingOutputCallRequestFieldTags = new uint[] { 26, 18, 8 };
-    public static StreamingOutputCallRequest DefaultInstance {
-      get { return defaultInstance; }
+  public sealed partial class StreamingOutputCallRequest : pb::IMessage<StreamingOutputCallRequest> {
+    private static readonly pb::MessageParser<StreamingOutputCallRequest> _parser = new pb::MessageParser<StreamingOutputCallRequest>(() => new StreamingOutputCallRequest());
+    public static pb::MessageParser<StreamingOutputCallRequest> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.Messages.Descriptor.MessageTypes[6]; }
     }
 
-    public override StreamingOutputCallRequest DefaultInstanceForType {
-      get { return DefaultInstance; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
-    protected override StreamingOutputCallRequest ThisMessage {
-      get { return this; }
+    public StreamingOutputCallRequest() {
+      OnConstruction();
     }
 
-    public static pbd::MessageDescriptor Descriptor {
-      get { return global::grpc.testing.Messages.internal__static_grpc_testing_StreamingOutputCallRequest__Descriptor; }
+    partial void OnConstruction();
+
+    public StreamingOutputCallRequest(StreamingOutputCallRequest other) : this() {
+      responseType_ = other.responseType_;
+      responseParameters_ = other.responseParameters_.Clone();
+      Payload = other.payload_ != null ? other.Payload.Clone() : null;
     }
 
-    protected override pb::FieldAccess.FieldAccessorTable<StreamingOutputCallRequest, StreamingOutputCallRequest.Builder> InternalFieldAccessors {
-      get { return global::grpc.testing.Messages.internal__static_grpc_testing_StreamingOutputCallRequest__FieldAccessorTable; }
+    public StreamingOutputCallRequest Clone() {
+      return new StreamingOutputCallRequest(this);
     }
 
     public const int ResponseTypeFieldNumber = 1;
-    private bool hasResponseType;
-    private global::grpc.testing.PayloadType responseType_ = global::grpc.testing.PayloadType.COMPRESSABLE;
-    public bool HasResponseType {
-      get { return hasResponseType; }
-    }
-    public global::grpc.testing.PayloadType ResponseType {
+    private global::Grpc.Testing.PayloadType responseType_ = global::Grpc.Testing.PayloadType.COMPRESSABLE;
+    public global::Grpc.Testing.PayloadType ResponseType {
       get { return responseType_; }
+      set {
+        responseType_ = value;
+      }
     }
 
     public const int ResponseParametersFieldNumber = 2;
-    private pbc::PopsicleList<global::grpc.testing.ResponseParameters> responseParameters_ = new pbc::PopsicleList<global::grpc.testing.ResponseParameters>();
-    public scg::IList<global::grpc.testing.ResponseParameters> ResponseParametersList {
+    private static readonly pb::FieldCodec<global::Grpc.Testing.ResponseParameters> _repeated_responseParameters_codec
+        = pb::FieldCodec.ForMessage(18, global::Grpc.Testing.ResponseParameters.Parser);
+    private readonly pbc::RepeatedField<global::Grpc.Testing.ResponseParameters> responseParameters_ = new pbc::RepeatedField<global::Grpc.Testing.ResponseParameters>();
+    public pbc::RepeatedField<global::Grpc.Testing.ResponseParameters> ResponseParameters {
       get { return responseParameters_; }
     }
-    public int ResponseParametersCount {
-      get { return responseParameters_.Count; }
-    }
-    public global::grpc.testing.ResponseParameters GetResponseParameters(int index) {
-      return responseParameters_[index];
-    }
 
     public const int PayloadFieldNumber = 3;
-    private bool hasPayload;
-    private global::grpc.testing.Payload payload_;
-    public bool HasPayload {
-      get { return hasPayload; }
-    }
-    public global::grpc.testing.Payload Payload {
-      get { return payload_ ?? global::grpc.testing.Payload.DefaultInstance; }
+    private global::Grpc.Testing.Payload payload_;
+    public global::Grpc.Testing.Payload Payload {
+      get { return payload_; }
+      set {
+        payload_ = value;
+      }
     }
 
-    public override bool IsInitialized {
-      get {
+    public override bool Equals(object other) {
+      return Equals(other as StreamingOutputCallRequest);
+    }
+
+    public bool Equals(StreamingOutputCallRequest other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
         return true;
       }
+      if (ResponseType != other.ResponseType) return false;
+      if(!responseParameters_.Equals(other.responseParameters_)) return false;
+      if (!object.Equals(Payload, other.Payload)) return false;
+      return true;
     }
 
-    public override void WriteTo(pb::ICodedOutputStream output) {
-      int size = SerializedSize;
-      string[] field_names = _streamingOutputCallRequestFieldNames;
-      if (hasResponseType) {
-        output.WriteEnum(1, field_names[2], (int) ResponseType, ResponseType);
-      }
-      if (responseParameters_.Count > 0) {
-        output.WriteMessageArray(2, field_names[1], responseParameters_);
-      }
-      if (hasPayload) {
-        output.WriteMessage(3, field_names[0], Payload);
-      }
-      UnknownFields.WriteTo(output);
+    public override int GetHashCode() {
+      int hash = 1;
+      if (ResponseType != global::Grpc.Testing.PayloadType.COMPRESSABLE) hash ^= ResponseType.GetHashCode();
+      hash ^= responseParameters_.GetHashCode();
+      if (payload_ != null) hash ^= Payload.GetHashCode();
+      return hash;
     }
 
-    private int memoizedSerializedSize = -1;
-    public override int SerializedSize {
-      get {
-        int size = memoizedSerializedSize;
-        if (size != -1) return size;
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
 
-        size = 0;
-        if (hasResponseType) {
-          size += pb::CodedOutputStream.ComputeEnumSize(1, (int) ResponseType);
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (ResponseType != global::Grpc.Testing.PayloadType.COMPRESSABLE) {
+        output.WriteRawTag(8);
+        output.WriteEnum((int) ResponseType);
+      }
+      responseParameters_.WriteTo(output, _repeated_responseParameters_codec);
+      if (payload_ != null) {
+        output.WriteRawTag(26);
+        output.WriteMessage(Payload);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (ResponseType != global::Grpc.Testing.PayloadType.COMPRESSABLE) {
+        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ResponseType);
+      }
+      size += responseParameters_.CalculateSize(_repeated_responseParameters_codec);
+      if (payload_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload);
+      }
+      return size;
+    }
+
+    public void MergeFrom(StreamingOutputCallRequest other) {
+      if (other == null) {
+        return;
+      }
+      if (other.ResponseType != global::Grpc.Testing.PayloadType.COMPRESSABLE) {
+        ResponseType = other.ResponseType;
+      }
+      responseParameters_.Add(other.responseParameters_);
+      if (other.payload_ != null) {
+        if (payload_ == null) {
+          payload_ = new global::Grpc.Testing.Payload();
         }
-        foreach (global::grpc.testing.ResponseParameters element in ResponseParametersList) {
-          size += pb::CodedOutputStream.ComputeMessageSize(2, element);
-        }
-        if (hasPayload) {
-          size += pb::CodedOutputStream.ComputeMessageSize(3, Payload);
-        }
-        size += UnknownFields.SerializedSize;
-        memoizedSerializedSize = size;
-        return size;
+        Payload.MergeFrom(other.Payload);
       }
     }
 
-    public static StreamingOutputCallRequest ParseFrom(pb::ByteString data) {
-      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
-    }
-    public static StreamingOutputCallRequest ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
-    }
-    public static StreamingOutputCallRequest ParseFrom(byte[] data) {
-      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
-    }
-    public static StreamingOutputCallRequest ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
-    }
-    public static StreamingOutputCallRequest ParseFrom(global::System.IO.Stream input) {
-      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
-    }
-    public static StreamingOutputCallRequest ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
-    }
-    public static StreamingOutputCallRequest ParseDelimitedFrom(global::System.IO.Stream input) {
-      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
-    }
-    public static StreamingOutputCallRequest ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
-      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
-    }
-    public static StreamingOutputCallRequest ParseFrom(pb::ICodedInputStream input) {
-      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
-    }
-    public static StreamingOutputCallRequest ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
-    }
-    private StreamingOutputCallRequest MakeReadOnly() {
-      responseParameters_.MakeReadOnly();
-      return this;
-    }
-
-    public static Builder CreateBuilder() { return new Builder(); }
-    public override Builder ToBuilder() { return CreateBuilder(this); }
-    public override Builder CreateBuilderForType() { return new Builder(); }
-    public static Builder CreateBuilder(StreamingOutputCallRequest prototype) {
-      return new Builder(prototype);
-    }
-
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-    public sealed partial class Builder : pb::GeneratedBuilder<StreamingOutputCallRequest, Builder> {
-      protected override Builder ThisBuilder {
-        get { return this; }
-      }
-      public Builder() {
-        result = DefaultInstance;
-        resultIsReadOnly = true;
-      }
-      internal Builder(StreamingOutputCallRequest cloneFrom) {
-        result = cloneFrom;
-        resultIsReadOnly = true;
-      }
-
-      private bool resultIsReadOnly;
-      private StreamingOutputCallRequest result;
-
-      private StreamingOutputCallRequest PrepareBuilder() {
-        if (resultIsReadOnly) {
-          StreamingOutputCallRequest original = result;
-          result = new StreamingOutputCallRequest();
-          resultIsReadOnly = false;
-          MergeFrom(original);
-        }
-        return result;
-      }
-
-      public override bool IsInitialized {
-        get { return result.IsInitialized; }
-      }
-
-      protected override StreamingOutputCallRequest MessageBeingBuilt {
-        get { return PrepareBuilder(); }
-      }
-
-      public override Builder Clear() {
-        result = DefaultInstance;
-        resultIsReadOnly = true;
-        return this;
-      }
-
-      public override Builder Clone() {
-        if (resultIsReadOnly) {
-          return new Builder(result);
-        } else {
-          return new Builder().MergeFrom(result);
-        }
-      }
-
-      public override pbd::MessageDescriptor DescriptorForType {
-        get { return global::grpc.testing.StreamingOutputCallRequest.Descriptor; }
-      }
-
-      public override StreamingOutputCallRequest DefaultInstanceForType {
-        get { return global::grpc.testing.StreamingOutputCallRequest.DefaultInstance; }
-      }
-
-      public override StreamingOutputCallRequest BuildPartial() {
-        if (resultIsReadOnly) {
-          return result;
-        }
-        resultIsReadOnly = true;
-        return result.MakeReadOnly();
-      }
-
-      public override Builder MergeFrom(pb::IMessage other) {
-        if (other is StreamingOutputCallRequest) {
-          return MergeFrom((StreamingOutputCallRequest) other);
-        } else {
-          base.MergeFrom(other);
-          return this;
-        }
-      }
-
-      public override Builder MergeFrom(StreamingOutputCallRequest other) {
-        if (other == global::grpc.testing.StreamingOutputCallRequest.DefaultInstance) return this;
-        PrepareBuilder();
-        if (other.HasResponseType) {
-          ResponseType = other.ResponseType;
-        }
-        if (other.responseParameters_.Count != 0) {
-          result.responseParameters_.Add(other.responseParameters_);
-        }
-        if (other.HasPayload) {
-          MergePayload(other.Payload);
-        }
-        this.MergeUnknownFields(other.UnknownFields);
-        return this;
-      }
-
-      public override Builder MergeFrom(pb::ICodedInputStream input) {
-        return MergeFrom(input, pb::ExtensionRegistry.Empty);
-      }
-
-      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
-        PrepareBuilder();
-        pb::UnknownFieldSet.Builder unknownFields = null;
-        uint tag;
-        string field_name;
-        while (input.ReadTag(out tag, out field_name)) {
-          if(tag == 0 && field_name != null) {
-            int field_ordinal = global::System.Array.BinarySearch(_streamingOutputCallRequestFieldNames, field_name, global::System.StringComparer.Ordinal);
-            if(field_ordinal >= 0)
-              tag = _streamingOutputCallRequestFieldTags[field_ordinal];
-            else {
-              if (unknownFields == null) {
-                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
-              }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
-              continue;
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while (input.ReadTag(out tag)) {
+        switch(tag) {
+          case 0:
+            throw pb::InvalidProtocolBufferException.InvalidTag();
+          default:
+            if (pb::WireFormat.IsEndGroupTag(tag)) {
+              return;
             }
+            break;
+          case 8: {
+            responseType_ = (global::Grpc.Testing.PayloadType) input.ReadEnum();
+            break;
           }
-          switch (tag) {
-            case 0: {
-              throw pb::InvalidProtocolBufferException.InvalidTag();
+          case 18: {
+            responseParameters_.AddEntriesFrom(input, _repeated_responseParameters_codec);
+            break;
+          }
+          case 26: {
+            if (payload_ == null) {
+              payload_ = new global::Grpc.Testing.Payload();
             }
-            default: {
-              if (pb::WireFormat.IsEndGroupTag(tag)) {
-                if (unknownFields != null) {
-                  this.UnknownFields = unknownFields.Build();
-                }
-                return this;
-              }
-              if (unknownFields == null) {
-                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
-              }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
-              break;
-            }
-            case 8: {
-              object unknown;
-              if(input.ReadEnum(ref result.responseType_, out unknown)) {
-                result.hasResponseType = true;
-              } else if(unknown is int) {
-                if (unknownFields == null) {
-                  unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
-                }
-                unknownFields.MergeVarintField(1, (ulong)(int)unknown);
-              }
-              break;
-            }
-            case 18: {
-              input.ReadMessageArray(tag, field_name, result.responseParameters_, global::grpc.testing.ResponseParameters.DefaultInstance, extensionRegistry);
-              break;
-            }
-            case 26: {
-              global::grpc.testing.Payload.Builder subBuilder = global::grpc.testing.Payload.CreateBuilder();
-              if (result.hasPayload) {
-                subBuilder.MergeFrom(Payload);
-              }
-              input.ReadMessage(subBuilder, extensionRegistry);
-              Payload = subBuilder.BuildPartial();
-              break;
-            }
+            input.ReadMessage(payload_);
+            break;
           }
         }
-
-        if (unknownFields != null) {
-          this.UnknownFields = unknownFields.Build();
-        }
-        return this;
-      }
-
-
-      public bool HasResponseType {
-       get { return result.hasResponseType; }
-      }
-      public global::grpc.testing.PayloadType ResponseType {
-        get { return result.ResponseType; }
-        set { SetResponseType(value); }
-      }
-      public Builder SetResponseType(global::grpc.testing.PayloadType value) {
-        PrepareBuilder();
-        result.hasResponseType = true;
-        result.responseType_ = value;
-        return this;
-      }
-      public Builder ClearResponseType() {
-        PrepareBuilder();
-        result.hasResponseType = false;
-        result.responseType_ = global::grpc.testing.PayloadType.COMPRESSABLE;
-        return this;
-      }
-
-      public pbc::IPopsicleList<global::grpc.testing.ResponseParameters> ResponseParametersList {
-        get { return PrepareBuilder().responseParameters_; }
-      }
-      public int ResponseParametersCount {
-        get { return result.ResponseParametersCount; }
-      }
-      public global::grpc.testing.ResponseParameters GetResponseParameters(int index) {
-        return result.GetResponseParameters(index);
-      }
-      public Builder SetResponseParameters(int index, global::grpc.testing.ResponseParameters value) {
-        pb::ThrowHelper.ThrowIfNull(value, "value");
-        PrepareBuilder();
-        result.responseParameters_[index] = value;
-        return this;
-      }
-      public Builder SetResponseParameters(int index, global::grpc.testing.ResponseParameters.Builder builderForValue) {
-        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
-        PrepareBuilder();
-        result.responseParameters_[index] = builderForValue.Build();
-        return this;
-      }
-      public Builder AddResponseParameters(global::grpc.testing.ResponseParameters value) {
-        pb::ThrowHelper.ThrowIfNull(value, "value");
-        PrepareBuilder();
-        result.responseParameters_.Add(value);
-        return this;
-      }
-      public Builder AddResponseParameters(global::grpc.testing.ResponseParameters.Builder builderForValue) {
-        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
-        PrepareBuilder();
-        result.responseParameters_.Add(builderForValue.Build());
-        return this;
-      }
-      public Builder AddRangeResponseParameters(scg::IEnumerable<global::grpc.testing.ResponseParameters> values) {
-        PrepareBuilder();
-        result.responseParameters_.Add(values);
-        return this;
-      }
-      public Builder ClearResponseParameters() {
-        PrepareBuilder();
-        result.responseParameters_.Clear();
-        return this;
-      }
-
-      public bool HasPayload {
-       get { return result.hasPayload; }
-      }
-      public global::grpc.testing.Payload Payload {
-        get { return result.Payload; }
-        set { SetPayload(value); }
-      }
-      public Builder SetPayload(global::grpc.testing.Payload value) {
-        pb::ThrowHelper.ThrowIfNull(value, "value");
-        PrepareBuilder();
-        result.hasPayload = true;
-        result.payload_ = value;
-        return this;
-      }
-      public Builder SetPayload(global::grpc.testing.Payload.Builder builderForValue) {
-        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
-        PrepareBuilder();
-        result.hasPayload = true;
-        result.payload_ = builderForValue.Build();
-        return this;
-      }
-      public Builder MergePayload(global::grpc.testing.Payload value) {
-        pb::ThrowHelper.ThrowIfNull(value, "value");
-        PrepareBuilder();
-        if (result.hasPayload &&
-            result.payload_ != global::grpc.testing.Payload.DefaultInstance) {
-            result.payload_ = global::grpc.testing.Payload.CreateBuilder(result.payload_).MergeFrom(value).BuildPartial();
-        } else {
-          result.payload_ = value;
-        }
-        result.hasPayload = true;
-        return this;
-      }
-      public Builder ClearPayload() {
-        PrepareBuilder();
-        result.hasPayload = false;
-        result.payload_ = null;
-        return this;
       }
     }
-    static StreamingOutputCallRequest() {
-      object.ReferenceEquals(global::grpc.testing.Messages.Descriptor, null);
-    }
+
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class StreamingOutputCallResponse : pb::GeneratedMessage<StreamingOutputCallResponse, StreamingOutputCallResponse.Builder> {
-    private StreamingOutputCallResponse() { }
-    private static readonly StreamingOutputCallResponse defaultInstance = new StreamingOutputCallResponse().MakeReadOnly();
-    private static readonly string[] _streamingOutputCallResponseFieldNames = new string[] { "payload" };
-    private static readonly uint[] _streamingOutputCallResponseFieldTags = new uint[] { 10 };
-    public static StreamingOutputCallResponse DefaultInstance {
-      get { return defaultInstance; }
+  public sealed partial class StreamingOutputCallResponse : pb::IMessage<StreamingOutputCallResponse> {
+    private static readonly pb::MessageParser<StreamingOutputCallResponse> _parser = new pb::MessageParser<StreamingOutputCallResponse>(() => new StreamingOutputCallResponse());
+    public static pb::MessageParser<StreamingOutputCallResponse> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.Messages.Descriptor.MessageTypes[7]; }
     }
 
-    public override StreamingOutputCallResponse DefaultInstanceForType {
-      get { return DefaultInstance; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
-    protected override StreamingOutputCallResponse ThisMessage {
-      get { return this; }
+    public StreamingOutputCallResponse() {
+      OnConstruction();
     }
 
-    public static pbd::MessageDescriptor Descriptor {
-      get { return global::grpc.testing.Messages.internal__static_grpc_testing_StreamingOutputCallResponse__Descriptor; }
+    partial void OnConstruction();
+
+    public StreamingOutputCallResponse(StreamingOutputCallResponse other) : this() {
+      Payload = other.payload_ != null ? other.Payload.Clone() : null;
     }
 
-    protected override pb::FieldAccess.FieldAccessorTable<StreamingOutputCallResponse, StreamingOutputCallResponse.Builder> InternalFieldAccessors {
-      get { return global::grpc.testing.Messages.internal__static_grpc_testing_StreamingOutputCallResponse__FieldAccessorTable; }
+    public StreamingOutputCallResponse Clone() {
+      return new StreamingOutputCallResponse(this);
     }
 
     public const int PayloadFieldNumber = 1;
-    private bool hasPayload;
-    private global::grpc.testing.Payload payload_;
-    public bool HasPayload {
-      get { return hasPayload; }
-    }
-    public global::grpc.testing.Payload Payload {
-      get { return payload_ ?? global::grpc.testing.Payload.DefaultInstance; }
+    private global::Grpc.Testing.Payload payload_;
+    public global::Grpc.Testing.Payload Payload {
+      get { return payload_; }
+      set {
+        payload_ = value;
+      }
     }
 
-    public override bool IsInitialized {
-      get {
+    public override bool Equals(object other) {
+      return Equals(other as StreamingOutputCallResponse);
+    }
+
+    public bool Equals(StreamingOutputCallResponse other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
         return true;
       }
+      if (!object.Equals(Payload, other.Payload)) return false;
+      return true;
     }
 
-    public override void WriteTo(pb::ICodedOutputStream output) {
-      int size = SerializedSize;
-      string[] field_names = _streamingOutputCallResponseFieldNames;
-      if (hasPayload) {
-        output.WriteMessage(1, field_names[0], Payload);
+    public override int GetHashCode() {
+      int hash = 1;
+      if (payload_ != null) hash ^= Payload.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (payload_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(Payload);
       }
-      UnknownFields.WriteTo(output);
     }
 
-    private int memoizedSerializedSize = -1;
-    public override int SerializedSize {
-      get {
-        int size = memoizedSerializedSize;
-        if (size != -1) return size;
+    public int CalculateSize() {
+      int size = 0;
+      if (payload_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload);
+      }
+      return size;
+    }
 
-        size = 0;
-        if (hasPayload) {
-          size += pb::CodedOutputStream.ComputeMessageSize(1, Payload);
+    public void MergeFrom(StreamingOutputCallResponse other) {
+      if (other == null) {
+        return;
+      }
+      if (other.payload_ != null) {
+        if (payload_ == null) {
+          payload_ = new global::Grpc.Testing.Payload();
         }
-        size += UnknownFields.SerializedSize;
-        memoizedSerializedSize = size;
-        return size;
+        Payload.MergeFrom(other.Payload);
       }
     }
 
-    public static StreamingOutputCallResponse ParseFrom(pb::ByteString data) {
-      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
-    }
-    public static StreamingOutputCallResponse ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
-    }
-    public static StreamingOutputCallResponse ParseFrom(byte[] data) {
-      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
-    }
-    public static StreamingOutputCallResponse ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
-    }
-    public static StreamingOutputCallResponse ParseFrom(global::System.IO.Stream input) {
-      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
-    }
-    public static StreamingOutputCallResponse ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
-    }
-    public static StreamingOutputCallResponse ParseDelimitedFrom(global::System.IO.Stream input) {
-      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
-    }
-    public static StreamingOutputCallResponse ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
-      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
-    }
-    public static StreamingOutputCallResponse ParseFrom(pb::ICodedInputStream input) {
-      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
-    }
-    public static StreamingOutputCallResponse ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
-      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
-    }
-    private StreamingOutputCallResponse MakeReadOnly() {
-      return this;
-    }
-
-    public static Builder CreateBuilder() { return new Builder(); }
-    public override Builder ToBuilder() { return CreateBuilder(this); }
-    public override Builder CreateBuilderForType() { return new Builder(); }
-    public static Builder CreateBuilder(StreamingOutputCallResponse prototype) {
-      return new Builder(prototype);
-    }
-
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-    public sealed partial class Builder : pb::GeneratedBuilder<StreamingOutputCallResponse, Builder> {
-      protected override Builder ThisBuilder {
-        get { return this; }
-      }
-      public Builder() {
-        result = DefaultInstance;
-        resultIsReadOnly = true;
-      }
-      internal Builder(StreamingOutputCallResponse cloneFrom) {
-        result = cloneFrom;
-        resultIsReadOnly = true;
-      }
-
-      private bool resultIsReadOnly;
-      private StreamingOutputCallResponse result;
-
-      private StreamingOutputCallResponse PrepareBuilder() {
-        if (resultIsReadOnly) {
-          StreamingOutputCallResponse original = result;
-          result = new StreamingOutputCallResponse();
-          resultIsReadOnly = false;
-          MergeFrom(original);
-        }
-        return result;
-      }
-
-      public override bool IsInitialized {
-        get { return result.IsInitialized; }
-      }
-
-      protected override StreamingOutputCallResponse MessageBeingBuilt {
-        get { return PrepareBuilder(); }
-      }
-
-      public override Builder Clear() {
-        result = DefaultInstance;
-        resultIsReadOnly = true;
-        return this;
-      }
-
-      public override Builder Clone() {
-        if (resultIsReadOnly) {
-          return new Builder(result);
-        } else {
-          return new Builder().MergeFrom(result);
-        }
-      }
-
-      public override pbd::MessageDescriptor DescriptorForType {
-        get { return global::grpc.testing.StreamingOutputCallResponse.Descriptor; }
-      }
-
-      public override StreamingOutputCallResponse DefaultInstanceForType {
-        get { return global::grpc.testing.StreamingOutputCallResponse.DefaultInstance; }
-      }
-
-      public override StreamingOutputCallResponse BuildPartial() {
-        if (resultIsReadOnly) {
-          return result;
-        }
-        resultIsReadOnly = true;
-        return result.MakeReadOnly();
-      }
-
-      public override Builder MergeFrom(pb::IMessage other) {
-        if (other is StreamingOutputCallResponse) {
-          return MergeFrom((StreamingOutputCallResponse) other);
-        } else {
-          base.MergeFrom(other);
-          return this;
-        }
-      }
-
-      public override Builder MergeFrom(StreamingOutputCallResponse other) {
-        if (other == global::grpc.testing.StreamingOutputCallResponse.DefaultInstance) return this;
-        PrepareBuilder();
-        if (other.HasPayload) {
-          MergePayload(other.Payload);
-        }
-        this.MergeUnknownFields(other.UnknownFields);
-        return this;
-      }
-
-      public override Builder MergeFrom(pb::ICodedInputStream input) {
-        return MergeFrom(input, pb::ExtensionRegistry.Empty);
-      }
-
-      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
-        PrepareBuilder();
-        pb::UnknownFieldSet.Builder unknownFields = null;
-        uint tag;
-        string field_name;
-        while (input.ReadTag(out tag, out field_name)) {
-          if(tag == 0 && field_name != null) {
-            int field_ordinal = global::System.Array.BinarySearch(_streamingOutputCallResponseFieldNames, field_name, global::System.StringComparer.Ordinal);
-            if(field_ordinal >= 0)
-              tag = _streamingOutputCallResponseFieldTags[field_ordinal];
-            else {
-              if (unknownFields == null) {
-                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
-              }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
-              continue;
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while (input.ReadTag(out tag)) {
+        switch(tag) {
+          case 0:
+            throw pb::InvalidProtocolBufferException.InvalidTag();
+          default:
+            if (pb::WireFormat.IsEndGroupTag(tag)) {
+              return;
             }
-          }
-          switch (tag) {
-            case 0: {
-              throw pb::InvalidProtocolBufferException.InvalidTag();
+            break;
+          case 10: {
+            if (payload_ == null) {
+              payload_ = new global::Grpc.Testing.Payload();
             }
-            default: {
-              if (pb::WireFormat.IsEndGroupTag(tag)) {
-                if (unknownFields != null) {
-                  this.UnknownFields = unknownFields.Build();
-                }
-                return this;
-              }
-              if (unknownFields == null) {
-                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
-              }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
-              break;
-            }
-            case 10: {
-              global::grpc.testing.Payload.Builder subBuilder = global::grpc.testing.Payload.CreateBuilder();
-              if (result.hasPayload) {
-                subBuilder.MergeFrom(Payload);
-              }
-              input.ReadMessage(subBuilder, extensionRegistry);
-              Payload = subBuilder.BuildPartial();
-              break;
-            }
+            input.ReadMessage(payload_);
+            break;
           }
         }
-
-        if (unknownFields != null) {
-          this.UnknownFields = unknownFields.Build();
-        }
-        return this;
-      }
-
-
-      public bool HasPayload {
-       get { return result.hasPayload; }
-      }
-      public global::grpc.testing.Payload Payload {
-        get { return result.Payload; }
-        set { SetPayload(value); }
-      }
-      public Builder SetPayload(global::grpc.testing.Payload value) {
-        pb::ThrowHelper.ThrowIfNull(value, "value");
-        PrepareBuilder();
-        result.hasPayload = true;
-        result.payload_ = value;
-        return this;
-      }
-      public Builder SetPayload(global::grpc.testing.Payload.Builder builderForValue) {
-        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
-        PrepareBuilder();
-        result.hasPayload = true;
-        result.payload_ = builderForValue.Build();
-        return this;
-      }
-      public Builder MergePayload(global::grpc.testing.Payload value) {
-        pb::ThrowHelper.ThrowIfNull(value, "value");
-        PrepareBuilder();
-        if (result.hasPayload &&
-            result.payload_ != global::grpc.testing.Payload.DefaultInstance) {
-            result.payload_ = global::grpc.testing.Payload.CreateBuilder(result.payload_).MergeFrom(value).BuildPartial();
-        } else {
-          result.payload_ = value;
-        }
-        result.hasPayload = true;
-        return this;
-      }
-      public Builder ClearPayload() {
-        PrepareBuilder();
-        result.hasPayload = false;
-        result.payload_ = null;
-        return this;
       }
     }
-    static StreamingOutputCallResponse() {
-      object.ReferenceEquals(global::grpc.testing.Messages.Descriptor, null);
-    }
+
   }
 
   #endregion
diff --git a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs
index 5223725..1b5a30d 100644
--- a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs
+++ b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs
@@ -12,13 +12,13 @@
   {
     static readonly string __ServiceName = "grpc.testing.TestService";
 
-    static readonly Marshaller<global::Grpc.Testing.Empty> __Marshaller_Empty = Marshallers.Create((arg) => arg.ToByteArray(), global::Grpc.Testing.Empty.ParseFrom);
-    static readonly Marshaller<global::Grpc.Testing.SimpleRequest> __Marshaller_SimpleRequest = Marshallers.Create((arg) => arg.ToByteArray(), global::Grpc.Testing.SimpleRequest.ParseFrom);
-    static readonly Marshaller<global::Grpc.Testing.SimpleResponse> __Marshaller_SimpleResponse = Marshallers.Create((arg) => arg.ToByteArray(), global::Grpc.Testing.SimpleResponse.ParseFrom);
-    static readonly Marshaller<global::Grpc.Testing.StreamingOutputCallRequest> __Marshaller_StreamingOutputCallRequest = Marshallers.Create((arg) => arg.ToByteArray(), global::Grpc.Testing.StreamingOutputCallRequest.ParseFrom);
-    static readonly Marshaller<global::Grpc.Testing.StreamingOutputCallResponse> __Marshaller_StreamingOutputCallResponse = Marshallers.Create((arg) => arg.ToByteArray(), global::Grpc.Testing.StreamingOutputCallResponse.ParseFrom);
-    static readonly Marshaller<global::Grpc.Testing.StreamingInputCallRequest> __Marshaller_StreamingInputCallRequest = Marshallers.Create((arg) => arg.ToByteArray(), global::Grpc.Testing.StreamingInputCallRequest.ParseFrom);
-    static readonly Marshaller<global::Grpc.Testing.StreamingInputCallResponse> __Marshaller_StreamingInputCallResponse = Marshallers.Create((arg) => arg.ToByteArray(), global::Grpc.Testing.StreamingInputCallResponse.ParseFrom);
+    static readonly Marshaller<global::Grpc.Testing.Empty> __Marshaller_Empty = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.Empty.Parser.ParseFrom);
+    static readonly Marshaller<global::Grpc.Testing.SimpleRequest> __Marshaller_SimpleRequest = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.SimpleRequest.Parser.ParseFrom);
+    static readonly Marshaller<global::Grpc.Testing.SimpleResponse> __Marshaller_SimpleResponse = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.SimpleResponse.Parser.ParseFrom);
+    static readonly Marshaller<global::Grpc.Testing.StreamingOutputCallRequest> __Marshaller_StreamingOutputCallRequest = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.StreamingOutputCallRequest.Parser.ParseFrom);
+    static readonly Marshaller<global::Grpc.Testing.StreamingOutputCallResponse> __Marshaller_StreamingOutputCallResponse = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.StreamingOutputCallResponse.Parser.ParseFrom);
+    static readonly Marshaller<global::Grpc.Testing.StreamingInputCallRequest> __Marshaller_StreamingInputCallRequest = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.StreamingInputCallRequest.Parser.ParseFrom);
+    static readonly Marshaller<global::Grpc.Testing.StreamingInputCallResponse> __Marshaller_StreamingInputCallResponse = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.StreamingInputCallResponse.Parser.ParseFrom);
 
     static readonly Method<global::Grpc.Testing.Empty, global::Grpc.Testing.Empty> __Method_EmptyCall = new Method<global::Grpc.Testing.Empty, global::Grpc.Testing.Empty>(
         MethodType.Unary,
