// 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 UnitTestRpcInterop {
  
    #region Extension registration
    public static void RegisterAllExtensions(pb::ExtensionRegistry registry) {
    }
    #endregion
    #region Static variables
    internal static pbd::MessageDescriptor internal__static_SearchRequest__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.SearchRequest, global::Google.ProtocolBuffers.TestProtos.SearchRequest.Builder> internal__static_SearchRequest__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_SearchResponse__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.SearchResponse, global::Google.ProtocolBuffers.TestProtos.SearchResponse.Builder> internal__static_SearchResponse__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_SearchResponse_ResultItem__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem, global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem.Builder> internal__static_SearchResponse_ResultItem__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_RefineSearchRequest__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.RefineSearchRequest, global::Google.ProtocolBuffers.TestProtos.RefineSearchRequest.Builder> internal__static_RefineSearchRequest__FieldAccessorTable;
    #endregion
    #region Descriptor
    public static pbd::FileDescriptor Descriptor {
      get { return descriptor; }
    }
    private static pbd::FileDescriptor descriptor;
    
    static UnitTestRpcInterop() {
      byte[] descriptorData = global::System.Convert.FromBase64String(
          "CiFleHRlc3QvdW5pdHRlc3RfcnBjX2ludGVyb3AucHJvdG8aJGdvb2dsZS9w" + 
          "cm90b2J1Zi9jc2hhcnBfb3B0aW9ucy5wcm90byIhCg1TZWFyY2hSZXF1ZXN0" + 
          "EhAKCENyaXRlcmlhGAEgAygJImYKDlNlYXJjaFJlc3BvbnNlEisKB3Jlc3Vs" + 
          "dHMYASADKAsyGi5TZWFyY2hSZXNwb25zZS5SZXN1bHRJdGVtGicKClJlc3Vs" + 
          "dEl0ZW0SCwoDdXJsGAEgAigJEgwKBG5hbWUYAiABKAkiUgoTUmVmaW5lU2Vh" + 
          "cmNoUmVxdWVzdBIQCghDcml0ZXJpYRgBIAMoCRIpChBwcmV2aW91c19yZXN1" + 
          "bHRzGAIgAigLMg8uU2VhcmNoUmVzcG9uc2UypQEKDVNlYXJjaFNlcnZpY2US" + 
          "MAoGU2VhcmNoEg4uU2VhcmNoUmVxdWVzdBoPLlNlYXJjaFJlc3BvbnNlIgXC" + 
          "PgIIBRI1CgxSZWZpbmVTZWFyY2gSFC5SZWZpbmVTZWFyY2hSZXF1ZXN0Gg8u" + 
          "U2VhcmNoUmVzcG9uc2UaK8I+KAome0E2NUYwOTI1LUZEMTEtNGY5NC1CMTY2" + 
          "LTg5QUM0RjAyNzIwNX1CP0gBwj46CiFHb29nbGUuUHJvdG9jb2xCdWZmZXJz" + 
          "LlRlc3RQcm90b3MSElVuaXRUZXN0UnBjSW50ZXJvcIgOAw==");
      pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {
        descriptor = root;
        internal__static_SearchRequest__Descriptor = Descriptor.MessageTypes[0];
        internal__static_SearchRequest__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.SearchRequest, global::Google.ProtocolBuffers.TestProtos.SearchRequest.Builder>(internal__static_SearchRequest__Descriptor,
                new string[] { "Criteria", });
        internal__static_SearchResponse__Descriptor = Descriptor.MessageTypes[1];
        internal__static_SearchResponse__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.SearchResponse, global::Google.ProtocolBuffers.TestProtos.SearchResponse.Builder>(internal__static_SearchResponse__Descriptor,
                new string[] { "Results", });
        internal__static_SearchResponse_ResultItem__Descriptor = internal__static_SearchResponse__Descriptor.NestedTypes[0];
        internal__static_SearchResponse_ResultItem__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem, global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem.Builder>(internal__static_SearchResponse_ResultItem__Descriptor,
                new string[] { "Url", "Name", });
        internal__static_RefineSearchRequest__Descriptor = Descriptor.MessageTypes[2];
        internal__static_RefineSearchRequest__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.RefineSearchRequest, global::Google.ProtocolBuffers.TestProtos.RefineSearchRequest.Builder>(internal__static_RefineSearchRequest__Descriptor,
                new string[] { "Criteria", "PreviousResults", });
        pb::ExtensionRegistry registry = pb::ExtensionRegistry.CreateInstance();
        RegisterAllExtensions(registry);
        global::Google.ProtocolBuffers.DescriptorProtos.CSharpOptions.RegisterAllExtensions(registry);
        return registry;
      };
      pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
          new pbd::FileDescriptor[] {
          global::Google.ProtocolBuffers.DescriptorProtos.CSharpOptions.Descriptor, 
          }, assigner);
    }
    #endregion
    
  }
  #region Messages
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
  [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
  public sealed partial class SearchRequest : pb::GeneratedMessage<SearchRequest, SearchRequest.Builder> {
    private static readonly SearchRequest defaultInstance = new Builder().BuildPartial();
    public static SearchRequest DefaultInstance {
      get { return defaultInstance; }
    }
    
    public override SearchRequest DefaultInstanceForType {
      get { return defaultInstance; }
    }
    
    protected override SearchRequest ThisMessage {
      get { return this; }
    }
    
    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.TestProtos.UnitTestRpcInterop.internal__static_SearchRequest__Descriptor; }
    }
    
    protected override pb::FieldAccess.FieldAccessorTable<SearchRequest, SearchRequest.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.TestProtos.UnitTestRpcInterop.internal__static_SearchRequest__FieldAccessorTable; }
    }
    
    public const int CriteriaFieldNumber = 1;
    private pbc::PopsicleList<string> criteria_ = new pbc::PopsicleList<string>();
    public scg::IList<string> CriteriaList {
      get { return pbc::Lists.AsReadOnly(criteria_); }
    }
    public int CriteriaCount {
      get { return criteria_.Count; }
    }
    public string GetCriteria(int index) {
      return criteria_[index];
    }
    
    public override bool IsInitialized {
      get {
        return true;
      }
    }
    
    public override void WriteTo(pb::ICodedOutputStream output) {
      int size = SerializedSize;
      if (criteria_.Count > 0) {
        output.WriteArray(pbd::FieldType.String, 1, "Criteria", criteria_);
      }
      UnknownFields.WriteTo(output);
    }
    
    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        
        size = 0;
        {
          int dataSize = 0;
          foreach (string element in CriteriaList) {
            dataSize += pb::CodedOutputStream.ComputeStringSizeNoTag(element);
          }
          size += dataSize;
          size += 1 * criteria_.Count;
        }
        size += UnknownFields.SerializedSize;
        memoizedSerializedSize = size;
        return size;
      }
    }
    
    public static SearchRequest ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static SearchRequest ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static SearchRequest ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static SearchRequest ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static SearchRequest ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static SearchRequest ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static SearchRequest ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static SearchRequest ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static SearchRequest ParseFrom(pb::CodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static SearchRequest ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    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(SearchRequest prototype) {
      return (Builder) new Builder().MergeFrom(prototype);
    }
    
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
    public sealed partial class Builder : pb::GeneratedBuilder<SearchRequest, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {}
      
      SearchRequest result = new SearchRequest();
      
      protected override SearchRequest MessageBeingBuilt {
        get { return result; }
      }
      
      public override Builder Clear() {
        result = new SearchRequest();
        return this;
      }
      
      public override Builder Clone() {
        return new Builder().MergeFrom(result);
      }
      
      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::Google.ProtocolBuffers.TestProtos.SearchRequest.Descriptor; }
      }
      
      public override SearchRequest DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.SearchRequest.DefaultInstance; }
      }
      
      public override SearchRequest BuildPartial() {
        if (result == null) {
          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
        }
        result.criteria_.MakeReadOnly();
        SearchRequest returnMe = result;
        result = null;
        return returnMe;
      }
      
      public override Builder MergeFrom(pb::IMessage other) {
        if (other is SearchRequest) {
          return MergeFrom((SearchRequest) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }
      
      public override Builder MergeFrom(SearchRequest other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.SearchRequest.DefaultInstance) return this;
        if (other.criteria_.Count != 0) {
          base.AddRange(other.criteria_, result.criteria_);
        }
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }
      
      public override Builder MergeFrom(pb::CodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }
      
      public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        pb::UnknownFieldSet.Builder unknownFields = null;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          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: {
              input.ReadPrimitiveArray(pbd::FieldType.String, tag, field_name, result.criteria_);
              break;
            }
          }
        }
        
        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }
      
      
      public pbc::IPopsicleList<string> CriteriaList {
        get { return result.criteria_; }
      }
      public int CriteriaCount {
        get { return result.CriteriaCount; }
      }
      public string GetCriteria(int index) {
        return result.GetCriteria(index);
      }
      public Builder SetCriteria(int index, string value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        result.criteria_[index] = value;
        return this;
      }
      public Builder AddCriteria(string value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        result.criteria_.Add(value);
        return this;
      }
      public Builder AddRangeCriteria(scg::IEnumerable<string> values) {
        base.AddRange(values, result.criteria_);
        return this;
      }
      public Builder ClearCriteria() {
        result.criteria_.Clear();
        return this;
      }
    }
    static SearchRequest() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnitTestRpcInterop.Descriptor, null);
    }
  }
  
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
  [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
  public sealed partial class SearchResponse : pb::GeneratedMessage<SearchResponse, SearchResponse.Builder> {
    private static readonly SearchResponse defaultInstance = new Builder().BuildPartial();
    public static SearchResponse DefaultInstance {
      get { return defaultInstance; }
    }
    
    public override SearchResponse DefaultInstanceForType {
      get { return defaultInstance; }
    }
    
    protected override SearchResponse ThisMessage {
      get { return this; }
    }
    
    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.TestProtos.UnitTestRpcInterop.internal__static_SearchResponse__Descriptor; }
    }
    
    protected override pb::FieldAccess.FieldAccessorTable<SearchResponse, SearchResponse.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.TestProtos.UnitTestRpcInterop.internal__static_SearchResponse__FieldAccessorTable; }
    }
    
    #region Nested types
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
    public static class Types {
      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
      [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
      [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
      public sealed partial class ResultItem : pb::GeneratedMessage<ResultItem, ResultItem.Builder> {
        private static readonly ResultItem defaultInstance = new Builder().BuildPartial();
        public static ResultItem DefaultInstance {
          get { return defaultInstance; }
        }
        
        public override ResultItem DefaultInstanceForType {
          get { return defaultInstance; }
        }
        
        protected override ResultItem ThisMessage {
          get { return this; }
        }
        
        public static pbd::MessageDescriptor Descriptor {
          get { return global::Google.ProtocolBuffers.TestProtos.UnitTestRpcInterop.internal__static_SearchResponse_ResultItem__Descriptor; }
        }
        
        protected override pb::FieldAccess.FieldAccessorTable<ResultItem, ResultItem.Builder> InternalFieldAccessors {
          get { return global::Google.ProtocolBuffers.TestProtos.UnitTestRpcInterop.internal__static_SearchResponse_ResultItem__FieldAccessorTable; }
        }
        
        public const int UrlFieldNumber = 1;
        private bool hasUrl;
        private string url_ = "";
        public bool HasUrl {
          get { return hasUrl; }
        }
        public string Url {
          get { return url_; }
        }
        
        public const int NameFieldNumber = 2;
        private bool hasName;
        private string name_ = "";
        public bool HasName {
          get { return hasName; }
        }
        public string Name {
          get { return name_; }
        }
        
        public override bool IsInitialized {
          get {
            if (!hasUrl) return false;
            return true;
          }
        }
        
        public override void WriteTo(pb::ICodedOutputStream output) {
          int size = SerializedSize;
          if (HasUrl) {
            output.WriteString(1, "url", Url);
          }
          if (HasName) {
            output.WriteString(2, "name", Name);
          }
          UnknownFields.WriteTo(output);
        }
        
        private int memoizedSerializedSize = -1;
        public override int SerializedSize {
          get {
            int size = memoizedSerializedSize;
            if (size != -1) return size;
            
            size = 0;
            if (HasUrl) {
              size += pb::CodedOutputStream.ComputeStringSize(1, Url);
            }
            if (HasName) {
              size += pb::CodedOutputStream.ComputeStringSize(2, Name);
            }
            size += UnknownFields.SerializedSize;
            memoizedSerializedSize = size;
            return size;
          }
        }
        
        public static ResultItem ParseFrom(pb::ByteString data) {
          return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
        }
        public static ResultItem ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
          return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
        }
        public static ResultItem ParseFrom(byte[] data) {
          return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
        }
        public static ResultItem ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
          return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
        }
        public static ResultItem ParseFrom(global::System.IO.Stream input) {
          return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
        }
        public static ResultItem ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
          return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
        }
        public static ResultItem ParseDelimitedFrom(global::System.IO.Stream input) {
          return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
        }
        public static ResultItem ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
          return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
        }
        public static ResultItem ParseFrom(pb::CodedInputStream input) {
          return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
        }
        public static ResultItem ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
          return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
        }
        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(ResultItem prototype) {
          return (Builder) new Builder().MergeFrom(prototype);
        }
        
        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
        [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
        public sealed partial class Builder : pb::GeneratedBuilder<ResultItem, Builder> {
          protected override Builder ThisBuilder {
            get { return this; }
          }
          public Builder() {}
          
          ResultItem result = new ResultItem();
          
          protected override ResultItem MessageBeingBuilt {
            get { return result; }
          }
          
          public override Builder Clear() {
            result = new ResultItem();
            return this;
          }
          
          public override Builder Clone() {
            return new Builder().MergeFrom(result);
          }
          
          public override pbd::MessageDescriptor DescriptorForType {
            get { return global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem.Descriptor; }
          }
          
          public override ResultItem DefaultInstanceForType {
            get { return global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem.DefaultInstance; }
          }
          
          public override ResultItem BuildPartial() {
            if (result == null) {
              throw new global::System.InvalidOperationException("build() has already been called on this Builder");
            }
            ResultItem returnMe = result;
            result = null;
            return returnMe;
          }
          
          public override Builder MergeFrom(pb::IMessage other) {
            if (other is ResultItem) {
              return MergeFrom((ResultItem) other);
            } else {
              base.MergeFrom(other);
              return this;
            }
          }
          
          public override Builder MergeFrom(ResultItem other) {
            if (other == global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem.DefaultInstance) return this;
            if (other.HasUrl) {
              Url = other.Url;
            }
            if (other.HasName) {
              Name = other.Name;
            }
            this.MergeUnknownFields(other.UnknownFields);
            return this;
          }
          
          public override Builder MergeFrom(pb::CodedInputStream input) {
            return MergeFrom(input, pb::ExtensionRegistry.Empty);
          }
          
          public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
            pb::UnknownFieldSet.Builder unknownFields = null;
            uint tag;
            string field_name;
            while (input.ReadTag(out tag, out field_name)) {
              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: {
                  result.hasUrl |= input.ReadString(ref result.url_);
                  break;
                }
                case 18: {
                  result.hasName |= input.ReadString(ref result.name_);
                  break;
                }
              }
            }
            
            if (unknownFields != null) {
              this.UnknownFields = unknownFields.Build();
            }
            return this;
          }
          
          
          public bool HasUrl {
            get { return result.HasUrl; }
          }
          public string Url {
            get { return result.Url; }
            set { SetUrl(value); }
          }
          public Builder SetUrl(string value) {
            pb::ThrowHelper.ThrowIfNull(value, "value");
            result.hasUrl = true;
            result.url_ = value;
            return this;
          }
          public Builder ClearUrl() {
            result.hasUrl = false;
            result.url_ = "";
            return this;
          }
          
          public bool HasName {
            get { return result.HasName; }
          }
          public string Name {
            get { return result.Name; }
            set { SetName(value); }
          }
          public Builder SetName(string value) {
            pb::ThrowHelper.ThrowIfNull(value, "value");
            result.hasName = true;
            result.name_ = value;
            return this;
          }
          public Builder ClearName() {
            result.hasName = false;
            result.name_ = "";
            return this;
          }
        }
        static ResultItem() {
          object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnitTestRpcInterop.Descriptor, null);
        }
      }
      
    }
    #endregion
    
    public const int ResultsFieldNumber = 1;
    private pbc::PopsicleList<global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem> results_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem>();
    public scg::IList<global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem> ResultsList {
      get { return results_; }
    }
    public int ResultsCount {
      get { return results_.Count; }
    }
    public global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem GetResults(int index) {
      return results_[index];
    }
    
    public override bool IsInitialized {
      get {
        foreach (global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem element in ResultsList) {
          if (!element.IsInitialized) return false;
        }
        return true;
      }
    }
    
    public override void WriteTo(pb::ICodedOutputStream output) {
      int size = SerializedSize;
      if (results_.Count > 0) {
        output.WriteArray(pbd::FieldType.Message, 1, "results", results_);
      }
      UnknownFields.WriteTo(output);
    }
    
    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        
        size = 0;
        foreach (global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem element in ResultsList) {
          size += pb::CodedOutputStream.ComputeMessageSize(1, element);
        }
        size += UnknownFields.SerializedSize;
        memoizedSerializedSize = size;
        return size;
      }
    }
    
    public static SearchResponse ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static SearchResponse ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static SearchResponse ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static SearchResponse ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static SearchResponse ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static SearchResponse ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static SearchResponse ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static SearchResponse ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static SearchResponse ParseFrom(pb::CodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static SearchResponse ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    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(SearchResponse prototype) {
      return (Builder) new Builder().MergeFrom(prototype);
    }
    
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
    public sealed partial class Builder : pb::GeneratedBuilder<SearchResponse, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {}
      
      SearchResponse result = new SearchResponse();
      
      protected override SearchResponse MessageBeingBuilt {
        get { return result; }
      }
      
      public override Builder Clear() {
        result = new SearchResponse();
        return this;
      }
      
      public override Builder Clone() {
        return new Builder().MergeFrom(result);
      }
      
      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::Google.ProtocolBuffers.TestProtos.SearchResponse.Descriptor; }
      }
      
      public override SearchResponse DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.SearchResponse.DefaultInstance; }
      }
      
      public override SearchResponse BuildPartial() {
        if (result == null) {
          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
        }
        result.results_.MakeReadOnly();
        SearchResponse returnMe = result;
        result = null;
        return returnMe;
      }
      
      public override Builder MergeFrom(pb::IMessage other) {
        if (other is SearchResponse) {
          return MergeFrom((SearchResponse) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }
      
      public override Builder MergeFrom(SearchResponse other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.SearchResponse.DefaultInstance) return this;
        if (other.results_.Count != 0) {
          base.AddRange(other.results_, result.results_);
        }
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }
      
      public override Builder MergeFrom(pb::CodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }
      
      public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        pb::UnknownFieldSet.Builder unknownFields = null;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          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: {
              input.ReadMessageArray(tag, field_name, result.results_, global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem.DefaultInstance, extensionRegistry);
              break;
            }
          }
        }
        
        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }
      
      
      public pbc::IPopsicleList<global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem> ResultsList {
        get { return result.results_; }
      }
      public int ResultsCount {
        get { return result.ResultsCount; }
      }
      public global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem GetResults(int index) {
        return result.GetResults(index);
      }
      public Builder SetResults(int index, global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        result.results_[index] = value;
        return this;
      }
      public Builder SetResults(int index, global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem.Builder builderForValue) {
        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
        result.results_[index] = builderForValue.Build();
        return this;
      }
      public Builder AddResults(global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        result.results_.Add(value);
        return this;
      }
      public Builder AddResults(global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem.Builder builderForValue) {
        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
        result.results_.Add(builderForValue.Build());
        return this;
      }
      public Builder AddRangeResults(scg::IEnumerable<global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem> values) {
        base.AddRange(values, result.results_);
        return this;
      }
      public Builder ClearResults() {
        result.results_.Clear();
        return this;
      }
    }
    static SearchResponse() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnitTestRpcInterop.Descriptor, null);
    }
  }
  
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
  [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
  public sealed partial class RefineSearchRequest : pb::GeneratedMessage<RefineSearchRequest, RefineSearchRequest.Builder> {
    private static readonly RefineSearchRequest defaultInstance = new Builder().BuildPartial();
    public static RefineSearchRequest DefaultInstance {
      get { return defaultInstance; }
    }
    
    public override RefineSearchRequest DefaultInstanceForType {
      get { return defaultInstance; }
    }
    
    protected override RefineSearchRequest ThisMessage {
      get { return this; }
    }
    
    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.TestProtos.UnitTestRpcInterop.internal__static_RefineSearchRequest__Descriptor; }
    }
    
    protected override pb::FieldAccess.FieldAccessorTable<RefineSearchRequest, RefineSearchRequest.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.TestProtos.UnitTestRpcInterop.internal__static_RefineSearchRequest__FieldAccessorTable; }
    }
    
    public const int CriteriaFieldNumber = 1;
    private pbc::PopsicleList<string> criteria_ = new pbc::PopsicleList<string>();
    public scg::IList<string> CriteriaList {
      get { return pbc::Lists.AsReadOnly(criteria_); }
    }
    public int CriteriaCount {
      get { return criteria_.Count; }
    }
    public string GetCriteria(int index) {
      return criteria_[index];
    }
    
    public const int PreviousResultsFieldNumber = 2;
    private bool hasPreviousResults;
    private global::Google.ProtocolBuffers.TestProtos.SearchResponse previousResults_ = global::Google.ProtocolBuffers.TestProtos.SearchResponse.DefaultInstance;
    public bool HasPreviousResults {
      get { return hasPreviousResults; }
    }
    public global::Google.ProtocolBuffers.TestProtos.SearchResponse PreviousResults {
      get { return previousResults_; }
    }
    
    public override bool IsInitialized {
      get {
        if (!hasPreviousResults) return false;
        if (!PreviousResults.IsInitialized) return false;
        return true;
      }
    }
    
    public override void WriteTo(pb::ICodedOutputStream output) {
      int size = SerializedSize;
      if (criteria_.Count > 0) {
        output.WriteArray(pbd::FieldType.String, 1, "Criteria", criteria_);
      }
      if (HasPreviousResults) {
        output.WriteMessage(2, "previous_results", PreviousResults);
      }
      UnknownFields.WriteTo(output);
    }
    
    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        
        size = 0;
        {
          int dataSize = 0;
          foreach (string element in CriteriaList) {
            dataSize += pb::CodedOutputStream.ComputeStringSizeNoTag(element);
          }
          size += dataSize;
          size += 1 * criteria_.Count;
        }
        if (HasPreviousResults) {
          size += pb::CodedOutputStream.ComputeMessageSize(2, PreviousResults);
        }
        size += UnknownFields.SerializedSize;
        memoizedSerializedSize = size;
        return size;
      }
    }
    
    public static RefineSearchRequest ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static RefineSearchRequest ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static RefineSearchRequest ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static RefineSearchRequest ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static RefineSearchRequest ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static RefineSearchRequest ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static RefineSearchRequest ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static RefineSearchRequest ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static RefineSearchRequest ParseFrom(pb::CodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static RefineSearchRequest ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    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(RefineSearchRequest prototype) {
      return (Builder) new Builder().MergeFrom(prototype);
    }
    
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
    public sealed partial class Builder : pb::GeneratedBuilder<RefineSearchRequest, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {}
      
      RefineSearchRequest result = new RefineSearchRequest();
      
      protected override RefineSearchRequest MessageBeingBuilt {
        get { return result; }
      }
      
      public override Builder Clear() {
        result = new RefineSearchRequest();
        return this;
      }
      
      public override Builder Clone() {
        return new Builder().MergeFrom(result);
      }
      
      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::Google.ProtocolBuffers.TestProtos.RefineSearchRequest.Descriptor; }
      }
      
      public override RefineSearchRequest DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.RefineSearchRequest.DefaultInstance; }
      }
      
      public override RefineSearchRequest BuildPartial() {
        if (result == null) {
          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
        }
        result.criteria_.MakeReadOnly();
        RefineSearchRequest returnMe = result;
        result = null;
        return returnMe;
      }
      
      public override Builder MergeFrom(pb::IMessage other) {
        if (other is RefineSearchRequest) {
          return MergeFrom((RefineSearchRequest) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }
      
      public override Builder MergeFrom(RefineSearchRequest other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.RefineSearchRequest.DefaultInstance) return this;
        if (other.criteria_.Count != 0) {
          base.AddRange(other.criteria_, result.criteria_);
        }
        if (other.HasPreviousResults) {
          MergePreviousResults(other.PreviousResults);
        }
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }
      
      public override Builder MergeFrom(pb::CodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }
      
      public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        pb::UnknownFieldSet.Builder unknownFields = null;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          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: {
              input.ReadPrimitiveArray(pbd::FieldType.String, tag, field_name, result.criteria_);
              break;
            }
            case 18: {
              global::Google.ProtocolBuffers.TestProtos.SearchResponse.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.SearchResponse.CreateBuilder();
              if (HasPreviousResults) {
                subBuilder.MergeFrom(PreviousResults);
              }
              input.ReadMessage(subBuilder, extensionRegistry);
              PreviousResults = subBuilder.BuildPartial();
              break;
            }
          }
        }
        
        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }
      
      
      public pbc::IPopsicleList<string> CriteriaList {
        get { return result.criteria_; }
      }
      public int CriteriaCount {
        get { return result.CriteriaCount; }
      }
      public string GetCriteria(int index) {
        return result.GetCriteria(index);
      }
      public Builder SetCriteria(int index, string value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        result.criteria_[index] = value;
        return this;
      }
      public Builder AddCriteria(string value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        result.criteria_.Add(value);
        return this;
      }
      public Builder AddRangeCriteria(scg::IEnumerable<string> values) {
        base.AddRange(values, result.criteria_);
        return this;
      }
      public Builder ClearCriteria() {
        result.criteria_.Clear();
        return this;
      }
      
      public bool HasPreviousResults {
       get { return result.HasPreviousResults; }
      }
      public global::Google.ProtocolBuffers.TestProtos.SearchResponse PreviousResults {
        get { return result.PreviousResults; }
        set { SetPreviousResults(value); }
      }
      public Builder SetPreviousResults(global::Google.ProtocolBuffers.TestProtos.SearchResponse value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        result.hasPreviousResults = true;
        result.previousResults_ = value;
        return this;
      }
      public Builder SetPreviousResults(global::Google.ProtocolBuffers.TestProtos.SearchResponse.Builder builderForValue) {
        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
        result.hasPreviousResults = true;
        result.previousResults_ = builderForValue.Build();
        return this;
      }
      public Builder MergePreviousResults(global::Google.ProtocolBuffers.TestProtos.SearchResponse value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        if (result.HasPreviousResults &&
            result.previousResults_ != global::Google.ProtocolBuffers.TestProtos.SearchResponse.DefaultInstance) {
            result.previousResults_ = global::Google.ProtocolBuffers.TestProtos.SearchResponse.CreateBuilder(result.previousResults_).MergeFrom(value).BuildPartial();
        } else {
          result.previousResults_ = value;
        }
        result.hasPreviousResults = true;
        return this;
      }
      public Builder ClearPreviousResults() {
        result.hasPreviousResults = false;
        result.previousResults_ = global::Google.ProtocolBuffers.TestProtos.SearchResponse.DefaultInstance;
        return this;
      }
    }
    static RefineSearchRequest() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnitTestRpcInterop.Descriptor, null);
    }
  }
  
  #endregion
  
  #region Services
  [global::System.Runtime.InteropServices.GuidAttribute("a65f0925-fd11-4f94-b166-89ac4f027205")]
  [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
  [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
  public partial interface ISearchService {
    [global::System.Runtime.InteropServices.DispId(5)]
    global::Google.ProtocolBuffers.TestProtos.SearchResponse Search(global::Google.ProtocolBuffers.TestProtos.SearchRequest searchRequest);
    global::Google.ProtocolBuffers.TestProtos.SearchResponse RefineSearch(global::Google.ProtocolBuffers.TestProtos.RefineSearchRequest refineSearchRequest);
  }
  
  [global::System.CLSCompliant(false)]
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
  [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
  public partial class SearchService : ISearchService, pb::IRpcDispatch, global::System.IDisposable {
    private readonly bool dispose;
    private readonly pb::IRpcDispatch dispatch;
    public SearchService(pb::IRpcDispatch dispatch) : this(dispatch, true) {
    }
    public SearchService(pb::IRpcDispatch dispatch, bool dispose) {
      if (null == (this.dispatch = dispatch)) throw new global::System.ArgumentNullException();
      this.dispose = dispose && dispatch is global::System.IDisposable;
    }
    
    public void Dispose() {
      if (dispose) ((global::System.IDisposable)dispatch).Dispose();
    }
    
    TMessage pb::IRpcDispatch.CallMethod<TMessage, TBuilder>(string method, pb::IMessageLite request, pb::IBuilderLite<TMessage, TBuilder> response) {
      return dispatch.CallMethod(method, request, response);
    }
    
    public global::Google.ProtocolBuffers.TestProtos.SearchResponse Search(global::Google.ProtocolBuffers.TestProtos.SearchRequest searchRequest) {
       return dispatch.CallMethod("Search", searchRequest, global::Google.ProtocolBuffers.TestProtos.SearchResponse.CreateBuilder());
    }
    
    public global::Google.ProtocolBuffers.TestProtos.SearchResponse RefineSearch(global::Google.ProtocolBuffers.TestProtos.RefineSearchRequest refineSearchRequest) {
       return dispatch.CallMethod("RefineSearch", refineSearchRequest, global::Google.ProtocolBuffers.TestProtos.SearchResponse.CreateBuilder());
    }
    
    [global::System.CLSCompliant(false)]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
    public partial class Dispatch : pb::IRpcDispatch, global::System.IDisposable {
      private readonly bool dispose;
      private readonly ISearchService implementation;
      public Dispatch(ISearchService implementation) : this(implementation, true) {
      }
      public Dispatch(ISearchService implementation, bool dispose) {
        if (null == (this.implementation = implementation)) throw new global::System.ArgumentNullException();
        this.dispose = dispose && implementation is global::System.IDisposable;
      }
      
      public void Dispose() {
        if (dispose) ((global::System.IDisposable)implementation).Dispose();
      }
      
      public TMessage CallMethod<TMessage, TBuilder>(string methodName, pb::IMessageLite request, pb::IBuilderLite<TMessage, TBuilder> response)
        where TMessage : pb::IMessageLite<TMessage, TBuilder>
        where TBuilder : pb::IBuilderLite<TMessage, TBuilder> {
        switch(methodName) {
          case "Search": return response.MergeFrom(implementation.Search((global::Google.ProtocolBuffers.TestProtos.SearchRequest)request)).Build();
          case "RefineSearch": return response.MergeFrom(implementation.RefineSearch((global::Google.ProtocolBuffers.TestProtos.RefineSearchRequest)request)).Build();
          default: throw new global::System.MissingMethodException(typeof(ISearchService).FullName, methodName);
        }
      }
    }
    [global::System.CLSCompliant(false)]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
    public partial class ServerStub : pb::IRpcServerStub, global::System.IDisposable {
      private readonly bool dispose;
      private readonly pb::IRpcDispatch implementation;
      public ServerStub(ISearchService implementation) : this(implementation, true) {
      }
      public ServerStub(ISearchService implementation, bool dispose) : this(new Dispatch(implementation, dispose), dispose) {
      }
      public ServerStub(pb::IRpcDispatch implementation) : this(implementation, true) {
      }
      public ServerStub(pb::IRpcDispatch implementation, bool dispose) {
        if (null == (this.implementation = implementation)) throw new global::System.ArgumentNullException();
        this.dispose = dispose && implementation is global::System.IDisposable;
      }
      
      public void Dispose() {
        if (dispose) ((global::System.IDisposable)implementation).Dispose();
      }
      
      public pb::IMessageLite CallMethod(string methodName, pb::CodedInputStream input, pb::ExtensionRegistry registry) {
        switch(methodName) {
          case "Search": return implementation.CallMethod(methodName, global::Google.ProtocolBuffers.TestProtos.SearchRequest.ParseFrom(input, registry), global::Google.ProtocolBuffers.TestProtos.SearchResponse.CreateBuilder());
          case "RefineSearch": return implementation.CallMethod(methodName, global::Google.ProtocolBuffers.TestProtos.RefineSearchRequest.ParseFrom(input, registry), global::Google.ProtocolBuffers.TestProtos.SearchResponse.CreateBuilder());
          default: throw new global::System.MissingMethodException(typeof(ISearchService).FullName, methodName);
        }
      }
    }
  }
  #endregion
  
}
