// Generated by ProtoGen, Version=2.3.0.277, Culture=neutral, PublicKeyToken=17b3b1f090c3ea48.  DO NOT EDIT!

using pb = global::Google.ProtocolBuffers;
using pbc = global::Google.ProtocolBuffers.Collections;
using pbd = global::Google.ProtocolBuffers.Descriptors;
using scg = global::System.Collections.Generic;
namespace Google.ProtocolBuffers.TestProtos {
  
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
  [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
  public static partial class UnitTestGenericServices {
  
    #region Extension registration
    public static void RegisterAllExtensions(pb::ExtensionRegistry registry) {
    }
    #endregion
    #region Static variables
    #endregion
    #region Descriptor
    public static pbd::FileDescriptor Descriptor {
      get { return descriptor; }
    }
    private static pbd::FileDescriptor descriptor;
    
    static UnitTestGenericServices() {
      byte[] descriptorData = global::System.Convert.FromBase64String(
          "CiZleHRlc3QvdW5pdHRlc3RfZ2VuZXJpY19zZXJ2aWNlcy5wcm90bxIRcHJv" + 
          "dG9idWZfdW5pdHRlc3QaJGdvb2dsZS9wcm90b2J1Zi9jc2hhcnBfb3B0aW9u" + 
          "cy5wcm90bxoeZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0LnByb3RvGi1nb29n" + 
          "bGUvcHJvdG9idWYvdW5pdHRlc3RfY3VzdG9tX29wdGlvbnMucHJvdG8yoAEK" + 
          "ElRlc3RHZW5lcmljU2VydmljZRJECgNGb28SHS5wcm90b2J1Zl91bml0dGVz" + 
          "dC5Gb29SZXF1ZXN0Gh4ucHJvdG9idWZfdW5pdHRlc3QuRm9vUmVzcG9uc2US" + 
          "RAoDQmFyEh0ucHJvdG9idWZfdW5pdHRlc3QuQmFyUmVxdWVzdBoeLnByb3Rv" + 
          "YnVmX3VuaXR0ZXN0LkJhclJlc3BvbnNlMpUBCiNUZXN0R2VuZXJpY1NlcnZp" + 
          "Y2VXaXRoQ3VzdG9tT3B0aW9ucxJjCgNGb28SKS5wcm90b2J1Zl91bml0dGVz" + 
          "dC5DdXN0b21PcHRpb25Gb29SZXF1ZXN0GioucHJvdG9idWZfdW5pdHRlc3Qu" + 
          "Q3VzdG9tT3B0aW9uRm9vUmVzcG9uc2UiBeD6jB4CGgmQsose09uAy0lCREgB" + 
          "wj4/CiFHb29nbGUuUHJvdG9jb2xCdWZmZXJzLlRlc3RQcm90b3MSF1VuaXRU" + 
          "ZXN0R2VuZXJpY1NlcnZpY2VziA4B");
      pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {
        descriptor = root;
        pb::ExtensionRegistry registry = pb::ExtensionRegistry.CreateInstance();
        RegisterAllExtensions(registry);
        global::Google.ProtocolBuffers.DescriptorProtos.CSharpOptions.RegisterAllExtensions(registry);
        global::Google.ProtocolBuffers.TestProtos.UnitTestProtoFile.RegisterAllExtensions(registry);
        global::Google.ProtocolBuffers.TestProtos.UnitTestCustomOptionsProtoFile.RegisterAllExtensions(registry);
        return registry;
      };
      pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
          new pbd::FileDescriptor[] {
          global::Google.ProtocolBuffers.DescriptorProtos.CSharpOptions.Descriptor, 
          global::Google.ProtocolBuffers.TestProtos.UnitTestProtoFile.Descriptor, 
          global::Google.ProtocolBuffers.TestProtos.UnitTestCustomOptionsProtoFile.Descriptor, 
          }, assigner);
    }
    #endregion
    
  }
  #region Services
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
  [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
  public abstract class TestGenericService : pb::IService {
    public abstract void Foo(
        pb::IRpcController controller,
        global::Google.ProtocolBuffers.TestProtos.FooRequest request,
        global::System.Action<global::Google.ProtocolBuffers.TestProtos.FooResponse> done);
    public abstract void Bar(
        pb::IRpcController controller,
        global::Google.ProtocolBuffers.TestProtos.BarRequest request,
        global::System.Action<global::Google.ProtocolBuffers.TestProtos.BarResponse> done);
    
    public static pbd::ServiceDescriptor Descriptor {
      get { return UnitTestGenericServices.Descriptor.Services[0]; }
    }
    public pbd::ServiceDescriptor DescriptorForType {
      get { return Descriptor; }
    }
    
    public void CallMethod(
        pbd::MethodDescriptor method,
        pb::IRpcController controller,
        pb::IMessage request,
        global::System.Action<pb::IMessage> done) {
      if (method.Service != Descriptor) {
        throw new global::System.ArgumentException(
            "Service.CallMethod() given method descriptor for wrong service type.");
      }
      switch(method.Index) {
        case 0:
          this.Foo(controller, (global::Google.ProtocolBuffers.TestProtos.FooRequest) request,
              pb::RpcUtil.SpecializeCallback<global::Google.ProtocolBuffers.TestProtos.FooResponse>(
              done));
          return;
        case 1:
          this.Bar(controller, (global::Google.ProtocolBuffers.TestProtos.BarRequest) request,
              pb::RpcUtil.SpecializeCallback<global::Google.ProtocolBuffers.TestProtos.BarResponse>(
              done));
          return;
        default:
          throw new global::System.InvalidOperationException("Can't get here.");
      }
    }
    
    public pb::IMessage GetRequestPrototype(pbd::MethodDescriptor method) {
      if (method.Service != Descriptor) {
        throw new global::System.ArgumentException(
            "Service.GetRequestPrototype() given method descriptor for wrong service type.");
      }
      switch(method.Index) {
        case 0:
          return global::Google.ProtocolBuffers.TestProtos.FooRequest.DefaultInstance;
        case 1:
          return global::Google.ProtocolBuffers.TestProtos.BarRequest.DefaultInstance;
        default:
          throw new global::System.InvalidOperationException("Can't get here.");
      }
    }
    
    public pb::IMessage GetResponsePrototype(pbd::MethodDescriptor method) {
      if (method.Service != Descriptor) {
        throw new global::System.ArgumentException(
            "Service.GetResponsePrototype() given method descriptor for wrong service type.");
      }
      switch(method.Index) {
        case 0:
          return global::Google.ProtocolBuffers.TestProtos.FooResponse.DefaultInstance;
        case 1:
          return global::Google.ProtocolBuffers.TestProtos.BarResponse.DefaultInstance;
        default:
          throw new global::System.InvalidOperationException("Can't get here.");
      }
    }
    
    public static Stub CreateStub(pb::IRpcChannel channel) {
      return new Stub(channel);
    }
    
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
    public class Stub : global::Google.ProtocolBuffers.TestProtos.TestGenericService {
      internal Stub(pb::IRpcChannel channel) {
        this.channel = channel;
      }
      
      private readonly pb::IRpcChannel channel;
      
      public pb::IRpcChannel Channel {
        get { return channel; }
      }
      
      public override void Foo(
          pb::IRpcController controller,
          global::Google.ProtocolBuffers.TestProtos.FooRequest request,
          global::System.Action<global::Google.ProtocolBuffers.TestProtos.FooResponse> done) {
        channel.CallMethod(Descriptor.Methods[0],
            controller, request, global::Google.ProtocolBuffers.TestProtos.FooResponse.DefaultInstance,
            pb::RpcUtil.GeneralizeCallback<global::Google.ProtocolBuffers.TestProtos.FooResponse, global::Google.ProtocolBuffers.TestProtos.FooResponse.Builder>(done, global::Google.ProtocolBuffers.TestProtos.FooResponse.DefaultInstance));
      }
      
      public override void Bar(
          pb::IRpcController controller,
          global::Google.ProtocolBuffers.TestProtos.BarRequest request,
          global::System.Action<global::Google.ProtocolBuffers.TestProtos.BarResponse> done) {
        channel.CallMethod(Descriptor.Methods[1],
            controller, request, global::Google.ProtocolBuffers.TestProtos.BarResponse.DefaultInstance,
            pb::RpcUtil.GeneralizeCallback<global::Google.ProtocolBuffers.TestProtos.BarResponse, global::Google.ProtocolBuffers.TestProtos.BarResponse.Builder>(done, global::Google.ProtocolBuffers.TestProtos.BarResponse.DefaultInstance));
      }
    }
  }
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
  [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
  public abstract class TestGenericServiceWithCustomOptions : pb::IService {
    public abstract void Foo(
        pb::IRpcController controller,
        global::Google.ProtocolBuffers.TestProtos.CustomOptionFooRequest request,
        global::System.Action<global::Google.ProtocolBuffers.TestProtos.CustomOptionFooResponse> done);
    
    public static pbd::ServiceDescriptor Descriptor {
      get { return UnitTestGenericServices.Descriptor.Services[1]; }
    }
    public pbd::ServiceDescriptor DescriptorForType {
      get { return Descriptor; }
    }
    
    public void CallMethod(
        pbd::MethodDescriptor method,
        pb::IRpcController controller,
        pb::IMessage request,
        global::System.Action<pb::IMessage> done) {
      if (method.Service != Descriptor) {
        throw new global::System.ArgumentException(
            "Service.CallMethod() given method descriptor for wrong service type.");
      }
      switch(method.Index) {
        case 0:
          this.Foo(controller, (global::Google.ProtocolBuffers.TestProtos.CustomOptionFooRequest) request,
              pb::RpcUtil.SpecializeCallback<global::Google.ProtocolBuffers.TestProtos.CustomOptionFooResponse>(
              done));
          return;
        default:
          throw new global::System.InvalidOperationException("Can't get here.");
      }
    }
    
    public pb::IMessage GetRequestPrototype(pbd::MethodDescriptor method) {
      if (method.Service != Descriptor) {
        throw new global::System.ArgumentException(
            "Service.GetRequestPrototype() given method descriptor for wrong service type.");
      }
      switch(method.Index) {
        case 0:
          return global::Google.ProtocolBuffers.TestProtos.CustomOptionFooRequest.DefaultInstance;
        default:
          throw new global::System.InvalidOperationException("Can't get here.");
      }
    }
    
    public pb::IMessage GetResponsePrototype(pbd::MethodDescriptor method) {
      if (method.Service != Descriptor) {
        throw new global::System.ArgumentException(
            "Service.GetResponsePrototype() given method descriptor for wrong service type.");
      }
      switch(method.Index) {
        case 0:
          return global::Google.ProtocolBuffers.TestProtos.CustomOptionFooResponse.DefaultInstance;
        default:
          throw new global::System.InvalidOperationException("Can't get here.");
      }
    }
    
    public static Stub CreateStub(pb::IRpcChannel channel) {
      return new Stub(channel);
    }
    
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
    public class Stub : global::Google.ProtocolBuffers.TestProtos.TestGenericServiceWithCustomOptions {
      internal Stub(pb::IRpcChannel channel) {
        this.channel = channel;
      }
      
      private readonly pb::IRpcChannel channel;
      
      public pb::IRpcChannel Channel {
        get { return channel; }
      }
      
      public override void Foo(
          pb::IRpcController controller,
          global::Google.ProtocolBuffers.TestProtos.CustomOptionFooRequest request,
          global::System.Action<global::Google.ProtocolBuffers.TestProtos.CustomOptionFooResponse> done) {
        channel.CallMethod(Descriptor.Methods[0],
            controller, request, global::Google.ProtocolBuffers.TestProtos.CustomOptionFooResponse.DefaultInstance,
            pb::RpcUtil.GeneralizeCallback<global::Google.ProtocolBuffers.TestProtos.CustomOptionFooResponse, global::Google.ProtocolBuffers.TestProtos.CustomOptionFooResponse.Builder>(done, global::Google.ProtocolBuffers.TestProtos.CustomOptionFooResponse.DefaultInstance));
      }
    }
  }
  #endregion
  
}
