فهرست منبع

Added unit tests for Lite runtime services and serialization

csharptest 14 سال پیش
والد
کامیت
bac32faf56

+ 4 - 0
build/build.csproj

@@ -43,6 +43,7 @@
     <Protos Include="$(ProtosDirectory)\extest\unittest_extras_xmltest.proto" />
     <Protos Include="$(ProtosDirectory)\extest\unittest_generic_services.proto" />
     <Protos Include="$(ProtosDirectory)\extest\unittest_rpc_interop.proto" />
+    <Protos Include="$(ProtosDirectory)\extest\unittest_rpc_interop_lite.proto" />
     <Protos Include="$(ProtosDirectory)\google\protobuf\descriptor.proto" />
     <Protos Include="$(ProtosDirectory)\google\protobuf\csharp_options.proto" />
     <Protos Include="$(ProtosDirectory)\google\protobuf\unittest.proto" />
@@ -115,6 +116,9 @@
     <GeneratedSource Include="$(BuildTempDirectory)\UnitTestRpcInterop.cs">
       <TargetDirectory>$(SourceDirectory)\ProtocolBuffers.Test\TestProtos</TargetDirectory>
     </GeneratedSource>
+    <GeneratedSource Include="$(BuildTempDirectory)\UnitTestRpcInteropLite.cs">
+      <TargetDirectory>$(SourceDirectory)\ProtocolBuffersLite.Test\TestProtos</TargetDirectory>
+    </GeneratedSource>
     <GeneratedSource Include="$(BuildTempDirectory)\UnitTestGenericServices.cs">
       <TargetDirectory>$(SourceDirectory)\ProtocolBuffers.Test\TestProtos</TargetDirectory>
     </GeneratedSource>

+ 3 - 3
protos/extest/unittest_extras_lite.proto

@@ -101,8 +101,8 @@ extend TestUnpackedExtensionsLite {
   repeated UnpackedTypesForeignEnumLite unpacked_enum_extension_lite = 103;
 }
 
-enum UnpackedTypesForeignEnumLite {
-  FOREIGN_LITE_FOO = 4;
-  FOREIGN_LITE_BAR = 5;
+enum UnpackedTypesForeignEnumLite {
+  FOREIGN_LITE_FOO = 4;
+  FOREIGN_LITE_BAR = 5;
   FOREIGN_LITE_BAZ = 6;
 }

+ 35 - 0
protos/extest/unittest_rpc_interop_lite.proto

@@ -0,0 +1,35 @@
+// Additional options required for C# generation. File from copyright
+// line onwards is as per original distribution.
+import "google/protobuf/csharp_options.proto";
+option (google.protobuf.csharp_file_options).namespace = "Google.ProtocolBuffers.TestProtos";
+option (google.protobuf.csharp_file_options).umbrella_classname = "UnitTestRpcInteropLite";
+
+option (google.protobuf.csharp_file_options).service_generator_type = IRPCDISPATCH;
+
+option optimize_for = LITE_RUNTIME;
+package unittest_rpc_interop_lite;
+
+message SearchRequest {
+  repeated string Criteria = 1;
+}
+
+message SearchResponse {
+  message ResultItem {
+    required string url = 1;
+    optional string name = 2;
+  }
+  
+  repeated ResultItem results = 1;
+}
+
+message RefineSearchRequest {
+  repeated string Criteria = 1;
+  required SearchResponse previous_results = 2;
+}
+
+service SearchService {
+  option (google.protobuf.csharp_service_options).interface_id = "{A65F0925-FD11-4f94-B166-89AC4F027205}";
+  rpc Search (SearchRequest) returns (SearchResponse) { option (google.protobuf.csharp_method_options).dispatch_id = 5; };
+  
+  rpc RefineSearch (RefineSearchRequest) returns (SearchResponse);
+}

+ 2 - 1
src/ProtocolBuffers.sln

@@ -1,6 +1,6 @@
-
 Microsoft Visual Studio Solution File, Format Version 11.00
 # Visual Studio 2010
+
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "proto", "proto", "{1F896D5C-5FC2-4671-9216-781CB8187EC7}"
 	ProjectSection(SolutionItems) = preProject
 		..\protos\tutorial\addressbook.proto = ..\protos\tutorial\addressbook.proto
@@ -32,6 +32,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "unittest", "unittest", "{C8
 		..\protos\google\protobuf\unittest_no_generic_services.proto = ..\protos\google\protobuf\unittest_no_generic_services.proto
 		..\protos\google\protobuf\unittest_optimize_for.proto = ..\protos\google\protobuf\unittest_optimize_for.proto
 		..\protos\extest\unittest_rpc_interop.proto = ..\protos\extest\unittest_rpc_interop.proto
+		..\protos\extest\unittest_rpc_interop_lite.proto = ..\protos\extest\unittest_rpc_interop_lite.proto
 	EndProjectSection
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProtocolBuffers", "ProtocolBuffers\ProtocolBuffers.csproj", "{6908BDCE-D925-43F3-94AC-A531E6DF2591}"

+ 2 - 1
src/ProtocolBuffers2008.sln

@@ -1,6 +1,6 @@
-
 Microsoft Visual Studio Solution File, Format Version 10.00
 # Visual Studio 2008
+
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "proto", "proto", "{1F896D5C-5FC2-4671-9216-781CB8187EC7}"
 	ProjectSection(SolutionItems) = preProject
 		..\protos\tutorial\addressbook.proto = ..\protos\tutorial\addressbook.proto
@@ -32,6 +32,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "unittest", "unittest", "{C8
 		..\protos\google\protobuf\unittest_no_generic_services.proto = ..\protos\google\protobuf\unittest_no_generic_services.proto
 		..\protos\google\protobuf\unittest_optimize_for.proto = ..\protos\google\protobuf\unittest_optimize_for.proto
 		..\protos\extest\unittest_rpc_interop.proto = ..\protos\extest\unittest_rpc_interop.proto
+		..\protos\extest\unittest_rpc_interop_lite.proto = ..\protos\extest\unittest_rpc_interop_lite.proto
 	EndProjectSection
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProtocolBuffers", "ProtocolBuffers\ProtocolBuffers.csproj", "{6908BDCE-D925-43F3-94AC-A531E6DF2591}"

+ 7 - 0
src/ProtocolBuffersLite.Test/ProtocolBuffersLite.Test.csproj

@@ -66,8 +66,15 @@
     <Compile Include="TestProtos\UnitTestExtrasLiteProtoFile.cs" />
     <Compile Include="TestProtos\UnitTestImportLiteProtoFile.cs" />
     <Compile Include="TestProtos\UnitTestLiteProtoFile.cs" />
+    <Compile Include="TestProtos\UnitTestRpcInteropLite.cs" />
+    <Compile Include="TestRpcForMimeTypes.cs" />
+    <Compile Include="TestRpcGenerator.cs" />
   </ItemGroup>
   <ItemGroup>
+    <ProjectReference Include="..\ProtocolBuffers.Serialization\ProtocolBuffersLite.Serialization.csproj">
+      <Project>{E067A59D-9D0A-4A1F-92B1-38E4457241D1}</Project>
+      <Name>ProtocolBuffersLite.Serialization</Name>
+    </ProjectReference>
     <ProjectReference Include="..\ProtocolBuffers\ProtocolBuffersLite.csproj">
       <Project>{6969BDCE-D925-43F3-94AC-A531E6DF2591}</Project>
       <Name>ProtocolBuffersLite</Name>

+ 1405 - 0
src/ProtocolBuffersLite.Test/TestProtos/UnitTestRpcInteropLite.cs

@@ -0,0 +1,1405 @@
+// Generated by ProtoGen, Version=2.3.0.277, Culture=neutral, PublicKeyToken=17b3b1f090c3ea48.  DO NOT EDIT!
+#pragma warning disable 1591, 0612
+#region Designer generated code
+
+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 UnitTestRpcInteropLite {
+  
+    #region Extension registration
+    public static void RegisterAllExtensions(pb::ExtensionRegistry registry) {
+    }
+    #endregion
+    #region Static variables
+    #endregion
+    #region Extensions
+    internal static readonly object Descriptor;
+    static UnitTestRpcInteropLite() {
+      Descriptor = null;
+    }
+    #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::GeneratedMessageLite<SearchRequest, SearchRequest.Builder> {
+    private SearchRequest() { }
+    private static readonly SearchRequest defaultInstance = new SearchRequest().MakeReadOnly();
+    private static readonly string[] _searchRequestFieldNames = new string[] { "Criteria" };
+    private static readonly uint[] _searchRequestFieldTags = new uint[] { 10 };
+    public static SearchRequest DefaultInstance {
+      get { return defaultInstance; }
+    }
+    
+    public override SearchRequest DefaultInstanceForType {
+      get { return DefaultInstance; }
+    }
+    
+    protected override SearchRequest ThisMessage {
+      get { return this; }
+    }
+    
+    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;
+      string[] field_names = _searchRequestFieldNames;
+      if (criteria_.Count > 0) {
+        output.WriteStringArray(1, field_names[0], criteria_);
+      }
+    }
+    
+    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;
+        }
+        memoizedSerializedSize = size;
+        return size;
+      }
+    }
+    
+    #region Lite runtime methods
+    public override int GetHashCode() {
+      int hash = GetType().GetHashCode();
+      foreach(string i in criteria_)
+        hash ^= i.GetHashCode();
+      return hash;
+    }
+    
+    public override bool Equals(object obj) {
+      SearchRequest other = obj as SearchRequest;
+      if (other == null) return false;
+      if(criteria_.Count != other.criteria_.Count) return false;
+      for(int ix=0; ix < criteria_.Count; ix++)
+        if(!criteria_[ix].Equals(other.criteria_[ix])) return false;
+      return true;
+    }
+    
+    public override void PrintTo(global::System.IO.TextWriter writer) {
+      PrintField("Criteria", criteria_, writer);
+    }
+    #endregion
+    
+    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::ICodedInputStream input) {
+      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+    }
+    public static SearchRequest ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+    }
+    private SearchRequest MakeReadOnly() {
+      criteria_.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(SearchRequest prototype) {
+      return new Builder(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::GeneratedBuilderLite<SearchRequest, Builder> {
+      protected override Builder ThisBuilder {
+        get { return this; }
+      }
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(SearchRequest cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
+      
+      private bool resultIsReadOnly;
+      private SearchRequest result;
+      
+      private SearchRequest PrepareBuilder() {
+        if (resultIsReadOnly) {
+          SearchRequest original = result;
+          result = new SearchRequest();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
+      
+      protected override SearchRequest 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 SearchRequest DefaultInstanceForType {
+        get { return global::Google.ProtocolBuffers.TestProtos.SearchRequest.DefaultInstance; }
+      }
+      
+      public override SearchRequest BuildPartial() {
+        if (resultIsReadOnly) {
+          return result;
+        }
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
+      }
+      
+      public override Builder MergeFrom(pb::IMessageLite 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;
+        PrepareBuilder();
+        if (other.criteria_.Count != 0) {
+          result.criteria_.Add(other.criteria_);
+        }
+        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();
+        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(_searchRequestFieldNames, field_name, global::System.StringComparer.Ordinal);
+            if(field_ordinal >= 0)
+              tag = _searchRequestFieldTags[field_ordinal];
+            else {
+              ParseUnknownField(input, extensionRegistry, tag, field_name);
+              continue;
+            }
+          }
+          switch (tag) {
+            case 0: {
+              throw pb::InvalidProtocolBufferException.InvalidTag();
+            }
+            default: {
+              if (pb::WireFormat.IsEndGroupTag(tag)) {
+                return this;
+              }
+              ParseUnknownField(input, extensionRegistry, tag, field_name);
+              break;
+            }
+            case 10: {
+              input.ReadStringArray(tag, field_name, result.criteria_);
+              break;
+            }
+          }
+        }
+        
+        return this;
+      }
+      
+      
+      public pbc::IPopsicleList<string> CriteriaList {
+        get { return PrepareBuilder().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");
+        PrepareBuilder();
+        result.criteria_[index] = value;
+        return this;
+      }
+      public Builder AddCriteria(string value) {
+        pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
+        result.criteria_.Add(value);
+        return this;
+      }
+      public Builder AddRangeCriteria(scg::IEnumerable<string> values) {
+        PrepareBuilder();
+        result.criteria_.Add(values);
+        return this;
+      }
+      public Builder ClearCriteria() {
+        PrepareBuilder();
+        result.criteria_.Clear();
+        return this;
+      }
+    }
+    static SearchRequest() {
+      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnitTestRpcInteropLite.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::GeneratedMessageLite<SearchResponse, SearchResponse.Builder> {
+    private SearchResponse() { }
+    private static readonly SearchResponse defaultInstance = new SearchResponse().MakeReadOnly();
+    private static readonly string[] _searchResponseFieldNames = new string[] { "results" };
+    private static readonly uint[] _searchResponseFieldTags = new uint[] { 10 };
+    public static SearchResponse DefaultInstance {
+      get { return defaultInstance; }
+    }
+    
+    public override SearchResponse DefaultInstanceForType {
+      get { return DefaultInstance; }
+    }
+    
+    protected override SearchResponse ThisMessage {
+      get { return this; }
+    }
+    
+    #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::GeneratedMessageLite<ResultItem, ResultItem.Builder> {
+        private ResultItem() { }
+        private static readonly ResultItem defaultInstance = new ResultItem().MakeReadOnly();
+        private static readonly string[] _resultItemFieldNames = new string[] { "name", "url" };
+        private static readonly uint[] _resultItemFieldTags = new uint[] { 18, 10 };
+        public static ResultItem DefaultInstance {
+          get { return defaultInstance; }
+        }
+        
+        public override ResultItem DefaultInstanceForType {
+          get { return DefaultInstance; }
+        }
+        
+        protected override ResultItem ThisMessage {
+          get { return this; }
+        }
+        
+        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;
+          string[] field_names = _resultItemFieldNames;
+          if (hasUrl) {
+            output.WriteString(1, field_names[1], Url);
+          }
+          if (hasName) {
+            output.WriteString(2, field_names[0], Name);
+          }
+        }
+        
+        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);
+            }
+            memoizedSerializedSize = size;
+            return size;
+          }
+        }
+        
+        #region Lite runtime methods
+        public override int GetHashCode() {
+          int hash = GetType().GetHashCode();
+          if (hasUrl) hash ^= url_.GetHashCode();
+          if (hasName) hash ^= name_.GetHashCode();
+          return hash;
+        }
+        
+        public override bool Equals(object obj) {
+          ResultItem other = obj as ResultItem;
+          if (other == null) return false;
+          if (hasUrl != other.hasUrl || (hasUrl && !url_.Equals(other.url_))) return false;
+          if (hasName != other.hasName || (hasName && !name_.Equals(other.name_))) return false;
+          return true;
+        }
+        
+        public override void PrintTo(global::System.IO.TextWriter writer) {
+          PrintField("url", hasUrl, url_, writer);
+          PrintField("name", hasName, name_, writer);
+        }
+        #endregion
+        
+        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::ICodedInputStream input) {
+          return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+        }
+        public static ResultItem ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+          return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+        }
+        private ResultItem 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(ResultItem prototype) {
+          return new Builder(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::GeneratedBuilderLite<ResultItem, Builder> {
+          protected override Builder ThisBuilder {
+            get { return this; }
+          }
+          public Builder() {
+            result = DefaultInstance;
+            resultIsReadOnly = true;
+          }
+          internal Builder(ResultItem cloneFrom) {
+            result = cloneFrom;
+            resultIsReadOnly = true;
+          }
+          
+          private bool resultIsReadOnly;
+          private ResultItem result;
+          
+          private ResultItem PrepareBuilder() {
+            if (resultIsReadOnly) {
+              ResultItem original = result;
+              result = new ResultItem();
+              resultIsReadOnly = false;
+              MergeFrom(original);
+            }
+            return result;
+          }
+          
+          public override bool IsInitialized {
+            get { return result.IsInitialized; }
+          }
+          
+          protected override ResultItem 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 ResultItem DefaultInstanceForType {
+            get { return global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem.DefaultInstance; }
+          }
+          
+          public override ResultItem BuildPartial() {
+            if (resultIsReadOnly) {
+              return result;
+            }
+            resultIsReadOnly = true;
+            return result.MakeReadOnly();
+          }
+          
+          public override Builder MergeFrom(pb::IMessageLite 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;
+            PrepareBuilder();
+            if (other.HasUrl) {
+              Url = other.Url;
+            }
+            if (other.HasName) {
+              Name = other.Name;
+            }
+            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();
+            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(_resultItemFieldNames, field_name, global::System.StringComparer.Ordinal);
+                if(field_ordinal >= 0)
+                  tag = _resultItemFieldTags[field_ordinal];
+                else {
+                  ParseUnknownField(input, extensionRegistry, tag, field_name);
+                  continue;
+                }
+              }
+              switch (tag) {
+                case 0: {
+                  throw pb::InvalidProtocolBufferException.InvalidTag();
+                }
+                default: {
+                  if (pb::WireFormat.IsEndGroupTag(tag)) {
+                    return this;
+                  }
+                  ParseUnknownField(input, 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;
+                }
+              }
+            }
+            
+            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");
+            PrepareBuilder();
+            result.hasUrl = true;
+            result.url_ = value;
+            return this;
+          }
+          public Builder ClearUrl() {
+            PrepareBuilder();
+            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");
+            PrepareBuilder();
+            result.hasName = true;
+            result.name_ = value;
+            return this;
+          }
+          public Builder ClearName() {
+            PrepareBuilder();
+            result.hasName = false;
+            result.name_ = "";
+            return this;
+          }
+        }
+        static ResultItem() {
+          object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnitTestRpcInteropLite.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;
+      string[] field_names = _searchResponseFieldNames;
+      if (results_.Count > 0) {
+        output.WriteMessageArray(1, field_names[0], results_);
+      }
+    }
+    
+    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);
+        }
+        memoizedSerializedSize = size;
+        return size;
+      }
+    }
+    
+    #region Lite runtime methods
+    public override int GetHashCode() {
+      int hash = GetType().GetHashCode();
+      foreach(global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem i in results_)
+        hash ^= i.GetHashCode();
+      return hash;
+    }
+    
+    public override bool Equals(object obj) {
+      SearchResponse other = obj as SearchResponse;
+      if (other == null) return false;
+      if(results_.Count != other.results_.Count) return false;
+      for(int ix=0; ix < results_.Count; ix++)
+        if(!results_[ix].Equals(other.results_[ix])) return false;
+      return true;
+    }
+    
+    public override void PrintTo(global::System.IO.TextWriter writer) {
+      PrintField("results", results_, writer);
+    }
+    #endregion
+    
+    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::ICodedInputStream input) {
+      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+    }
+    public static SearchResponse ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+    }
+    private SearchResponse MakeReadOnly() {
+      results_.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(SearchResponse prototype) {
+      return new Builder(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::GeneratedBuilderLite<SearchResponse, Builder> {
+      protected override Builder ThisBuilder {
+        get { return this; }
+      }
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(SearchResponse cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
+      
+      private bool resultIsReadOnly;
+      private SearchResponse result;
+      
+      private SearchResponse PrepareBuilder() {
+        if (resultIsReadOnly) {
+          SearchResponse original = result;
+          result = new SearchResponse();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
+      
+      protected override SearchResponse 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 SearchResponse DefaultInstanceForType {
+        get { return global::Google.ProtocolBuffers.TestProtos.SearchResponse.DefaultInstance; }
+      }
+      
+      public override SearchResponse BuildPartial() {
+        if (resultIsReadOnly) {
+          return result;
+        }
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
+      }
+      
+      public override Builder MergeFrom(pb::IMessageLite 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;
+        PrepareBuilder();
+        if (other.results_.Count != 0) {
+          result.results_.Add(other.results_);
+        }
+        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();
+        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(_searchResponseFieldNames, field_name, global::System.StringComparer.Ordinal);
+            if(field_ordinal >= 0)
+              tag = _searchResponseFieldTags[field_ordinal];
+            else {
+              ParseUnknownField(input, extensionRegistry, tag, field_name);
+              continue;
+            }
+          }
+          switch (tag) {
+            case 0: {
+              throw pb::InvalidProtocolBufferException.InvalidTag();
+            }
+            default: {
+              if (pb::WireFormat.IsEndGroupTag(tag)) {
+                return this;
+              }
+              ParseUnknownField(input, extensionRegistry, tag, field_name);
+              break;
+            }
+            case 10: {
+              input.ReadMessageArray(tag, field_name, result.results_, global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem.DefaultInstance, extensionRegistry);
+              break;
+            }
+          }
+        }
+        
+        return this;
+      }
+      
+      
+      public pbc::IPopsicleList<global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem> ResultsList {
+        get { return PrepareBuilder().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");
+        PrepareBuilder();
+        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");
+        PrepareBuilder();
+        result.results_[index] = builderForValue.Build();
+        return this;
+      }
+      public Builder AddResults(global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem value) {
+        pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
+        result.results_.Add(value);
+        return this;
+      }
+      public Builder AddResults(global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem.Builder builderForValue) {
+        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
+        result.results_.Add(builderForValue.Build());
+        return this;
+      }
+      public Builder AddRangeResults(scg::IEnumerable<global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem> values) {
+        PrepareBuilder();
+        result.results_.Add(values);
+        return this;
+      }
+      public Builder ClearResults() {
+        PrepareBuilder();
+        result.results_.Clear();
+        return this;
+      }
+    }
+    static SearchResponse() {
+      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnitTestRpcInteropLite.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::GeneratedMessageLite<RefineSearchRequest, RefineSearchRequest.Builder> {
+    private RefineSearchRequest() { }
+    private static readonly RefineSearchRequest defaultInstance = new RefineSearchRequest().MakeReadOnly();
+    private static readonly string[] _refineSearchRequestFieldNames = new string[] { "Criteria", "previous_results" };
+    private static readonly uint[] _refineSearchRequestFieldTags = new uint[] { 10, 18 };
+    public static RefineSearchRequest DefaultInstance {
+      get { return defaultInstance; }
+    }
+    
+    public override RefineSearchRequest DefaultInstanceForType {
+      get { return DefaultInstance; }
+    }
+    
+    protected override RefineSearchRequest ThisMessage {
+      get { return this; }
+    }
+    
+    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_;
+    public bool HasPreviousResults {
+      get { return hasPreviousResults; }
+    }
+    public global::Google.ProtocolBuffers.TestProtos.SearchResponse PreviousResults {
+      get { return previousResults_ ?? global::Google.ProtocolBuffers.TestProtos.SearchResponse.DefaultInstance; }
+    }
+    
+    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;
+      string[] field_names = _refineSearchRequestFieldNames;
+      if (criteria_.Count > 0) {
+        output.WriteStringArray(1, field_names[0], criteria_);
+      }
+      if (hasPreviousResults) {
+        output.WriteMessage(2, field_names[1], PreviousResults);
+      }
+    }
+    
+    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);
+        }
+        memoizedSerializedSize = size;
+        return size;
+      }
+    }
+    
+    #region Lite runtime methods
+    public override int GetHashCode() {
+      int hash = GetType().GetHashCode();
+      foreach(string i in criteria_)
+        hash ^= i.GetHashCode();
+      if (hasPreviousResults) hash ^= previousResults_.GetHashCode();
+      return hash;
+    }
+    
+    public override bool Equals(object obj) {
+      RefineSearchRequest other = obj as RefineSearchRequest;
+      if (other == null) return false;
+      if(criteria_.Count != other.criteria_.Count) return false;
+      for(int ix=0; ix < criteria_.Count; ix++)
+        if(!criteria_[ix].Equals(other.criteria_[ix])) return false;
+      if (hasPreviousResults != other.hasPreviousResults || (hasPreviousResults && !previousResults_.Equals(other.previousResults_))) return false;
+      return true;
+    }
+    
+    public override void PrintTo(global::System.IO.TextWriter writer) {
+      PrintField("Criteria", criteria_, writer);
+      PrintField("previous_results", hasPreviousResults, previousResults_, writer);
+    }
+    #endregion
+    
+    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::ICodedInputStream input) {
+      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+    }
+    public static RefineSearchRequest ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+    }
+    private RefineSearchRequest MakeReadOnly() {
+      criteria_.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(RefineSearchRequest prototype) {
+      return new Builder(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::GeneratedBuilderLite<RefineSearchRequest, Builder> {
+      protected override Builder ThisBuilder {
+        get { return this; }
+      }
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(RefineSearchRequest cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
+      
+      private bool resultIsReadOnly;
+      private RefineSearchRequest result;
+      
+      private RefineSearchRequest PrepareBuilder() {
+        if (resultIsReadOnly) {
+          RefineSearchRequest original = result;
+          result = new RefineSearchRequest();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
+      
+      protected override RefineSearchRequest 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 RefineSearchRequest DefaultInstanceForType {
+        get { return global::Google.ProtocolBuffers.TestProtos.RefineSearchRequest.DefaultInstance; }
+      }
+      
+      public override RefineSearchRequest BuildPartial() {
+        if (resultIsReadOnly) {
+          return result;
+        }
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
+      }
+      
+      public override Builder MergeFrom(pb::IMessageLite 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;
+        PrepareBuilder();
+        if (other.criteria_.Count != 0) {
+          result.criteria_.Add(other.criteria_);
+        }
+        if (other.HasPreviousResults) {
+          MergePreviousResults(other.PreviousResults);
+        }
+        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();
+        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(_refineSearchRequestFieldNames, field_name, global::System.StringComparer.Ordinal);
+            if(field_ordinal >= 0)
+              tag = _refineSearchRequestFieldTags[field_ordinal];
+            else {
+              ParseUnknownField(input, extensionRegistry, tag, field_name);
+              continue;
+            }
+          }
+          switch (tag) {
+            case 0: {
+              throw pb::InvalidProtocolBufferException.InvalidTag();
+            }
+            default: {
+              if (pb::WireFormat.IsEndGroupTag(tag)) {
+                return this;
+              }
+              ParseUnknownField(input, extensionRegistry, tag, field_name);
+              break;
+            }
+            case 10: {
+              input.ReadStringArray(tag, field_name, result.criteria_);
+              break;
+            }
+            case 18: {
+              global::Google.ProtocolBuffers.TestProtos.SearchResponse.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.SearchResponse.CreateBuilder();
+              if (result.hasPreviousResults) {
+                subBuilder.MergeFrom(PreviousResults);
+              }
+              input.ReadMessage(subBuilder, extensionRegistry);
+              PreviousResults = subBuilder.BuildPartial();
+              break;
+            }
+          }
+        }
+        
+        return this;
+      }
+      
+      
+      public pbc::IPopsicleList<string> CriteriaList {
+        get { return PrepareBuilder().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");
+        PrepareBuilder();
+        result.criteria_[index] = value;
+        return this;
+      }
+      public Builder AddCriteria(string value) {
+        pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
+        result.criteria_.Add(value);
+        return this;
+      }
+      public Builder AddRangeCriteria(scg::IEnumerable<string> values) {
+        PrepareBuilder();
+        result.criteria_.Add(values);
+        return this;
+      }
+      public Builder ClearCriteria() {
+        PrepareBuilder();
+        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");
+        PrepareBuilder();
+        result.hasPreviousResults = true;
+        result.previousResults_ = value;
+        return this;
+      }
+      public Builder SetPreviousResults(global::Google.ProtocolBuffers.TestProtos.SearchResponse.Builder builderForValue) {
+        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
+        result.hasPreviousResults = true;
+        result.previousResults_ = builderForValue.Build();
+        return this;
+      }
+      public Builder MergePreviousResults(global::Google.ProtocolBuffers.TestProtos.SearchResponse value) {
+        pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
+        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() {
+        PrepareBuilder();
+        result.hasPreviousResults = false;
+        result.previousResults_ = null;
+        return this;
+      }
+    }
+    static RefineSearchRequest() {
+      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnitTestRpcInteropLite.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::ICodedInputStream 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
+  
+}
+
+#endregion Designer generated code

+ 386 - 0
src/ProtocolBuffersLite.Test/TestRpcForMimeTypes.cs

@@ -0,0 +1,386 @@
+#region Copyright notice and license
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using Google.ProtocolBuffers;
+using Google.ProtocolBuffers.Serialization.Http;
+using Google.ProtocolBuffers.TestProtos;
+using NUnit.Framework;
+using System.IO;
+using Google.ProtocolBuffers.Serialization;
+using System.Text;
+
+namespace Google.ProtocolBuffers
+{
+    /// <summary>
+    /// This class verifies the correct code is generated from unittest_rpc_interop.proto and provides a small demonstration
+    /// of using the new IRpcDispatch to write a client/server
+    /// </summary>
+    [TestFixture]
+    public class TestRpcForMimeTypes
+    {
+        /// <summary>
+        /// A sample implementation of the ISearchService for testing
+        /// </summary>
+        private class ExampleSearchImpl : ISearchService
+        {
+            SearchResponse ISearchService.Search(SearchRequest searchRequest)
+            {
+                if (searchRequest.CriteriaCount == 0)
+                {
+                    throw new ArgumentException("No criteria specified.", new InvalidOperationException());
+                }
+                SearchResponse.Builder resp = SearchResponse.CreateBuilder();
+                foreach (string criteria in searchRequest.CriteriaList)
+                {
+                    resp.AddResults(
+                        SearchResponse.Types.ResultItem.CreateBuilder().SetName(criteria).SetUrl("http://search.com").
+                            Build());
+                }
+                return resp.Build();
+            }
+
+            SearchResponse ISearchService.RefineSearch(RefineSearchRequest refineSearchRequest)
+            {
+                SearchResponse.Builder resp = refineSearchRequest.PreviousResults.ToBuilder();
+                foreach (string criteria in refineSearchRequest.CriteriaList)
+                {
+                    resp.AddResults(
+                        SearchResponse.Types.ResultItem.CreateBuilder().SetName(criteria).SetUrl("http://refine.com").
+                            Build());
+                }
+                return resp.Build();
+            }
+        }
+
+        /// <summary>
+        /// An example extraction of the wire protocol
+        /// </summary>
+        private interface IHttpTransfer
+        {
+            void Execute(string method, string contentType, Stream input, string acceptType, Stream output);
+        }
+
+        /// <summary>
+        /// An example of a server responding to a web/http request
+        /// </summary>
+        private class ExampleHttpServer : IHttpTransfer
+        {
+            public readonly MessageFormatOptions Options =
+                new MessageFormatOptions
+                {
+                    ExtensionRegistry = ExtensionRegistry.Empty,
+                    FormattedOutput = true,
+                    XmlReaderOptions = XmlReaderOptions.ReadNestedArrays,
+                    XmlReaderRootElementName = "request",
+                    XmlWriterOptions = XmlWriterOptions.OutputNestedArrays,
+                    XmlWriterRootElementName = "response"
+                };
+
+            private readonly IRpcServerStub _stub;
+
+            public ExampleHttpServer(ISearchService implementation)
+            {
+                //on the server, we create a dispatch to call the appropriate method by name
+                IRpcDispatch dispatch = new SearchService.Dispatch(implementation);
+                //we then wrap that dispatch in a server stub which will deserialize the wire bytes to the message
+                //type appropriate for the method name being invoked.
+                _stub = new SearchService.ServerStub(dispatch);
+            }
+
+            void IHttpTransfer.Execute(string method, string contentType, Stream input, string acceptType, Stream output)
+            {
+                //Extension for: Google.ProtocolBuffers.Serialization.Http.ServiceExtensions.HttpCallMethod(_stub,
+                _stub.HttpCallMethod(
+                    method, Options,
+                    contentType, input,
+                    acceptType, output
+                    );
+            }
+        }
+
+        /// <summary>
+        /// An example of a client sending a wire request
+        /// </summary>
+        private class ExampleClient : IRpcDispatch
+        {
+            public readonly MessageFormatOptions Options =
+                new MessageFormatOptions
+                {
+                    ExtensionRegistry = ExtensionRegistry.Empty,
+                    FormattedOutput = true,
+                    XmlReaderOptions = XmlReaderOptions.ReadNestedArrays,
+                    XmlReaderRootElementName = "response",
+                    XmlWriterOptions = XmlWriterOptions.OutputNestedArrays,
+                    XmlWriterRootElementName = "request"
+                };
+
+
+            private readonly IHttpTransfer _wire;
+            private readonly string _mimeType;
+
+            public ExampleClient(IHttpTransfer wire, string mimeType)
+            {
+                _wire = wire;
+                _mimeType = mimeType;
+            }
+
+            TMessage IRpcDispatch.CallMethod<TMessage, TBuilder>(string method, IMessageLite request,
+                                                                 IBuilderLite<TMessage, TBuilder> response)
+            {
+                MemoryStream input = new MemoryStream();
+                MemoryStream output = new MemoryStream();
+
+                //Write to _mimeType format
+                request.WriteTo(Options, _mimeType, input);
+
+                input.Position = 0;
+                _wire.Execute(method, _mimeType, input, _mimeType, output);
+
+                //Read from _mimeType format
+                output.Position = 0;
+                response.MergeFrom(Options, _mimeType, output);
+                
+                return response.Build();
+            }
+        }
+
+        /// <summary>
+        /// Test sending and recieving messages via text/json
+        /// </summary>
+        [Test]
+        public void TestClientServerWithJsonFormat()
+        {
+            ExampleHttpServer server = new ExampleHttpServer(new ExampleSearchImpl());
+            //obviously if this was a 'real' transport we would not use the server, rather the server would be listening, the client transmitting
+            IHttpTransfer wire = server;
+
+            ISearchService client = new SearchService(new ExampleClient(wire, "text/json"));
+            //now the client has a real, typed, interface to work with:
+            SearchResponse result = client.Search(SearchRequest.CreateBuilder().AddCriteria("Test").Build());
+            Assert.AreEqual(1, result.ResultsCount);
+            Assert.AreEqual("Test", result.ResultsList[0].Name);
+            Assert.AreEqual("http://search.com", result.ResultsList[0].Url);
+
+            //The test part of this, call the only other method
+            result =
+                client.RefineSearch(
+                    RefineSearchRequest.CreateBuilder().SetPreviousResults(result).AddCriteria("Refine").Build());
+            Assert.AreEqual(2, result.ResultsCount);
+            Assert.AreEqual("Test", result.ResultsList[0].Name);
+            Assert.AreEqual("http://search.com", result.ResultsList[0].Url);
+
+            Assert.AreEqual("Refine", result.ResultsList[1].Name);
+            Assert.AreEqual("http://refine.com", result.ResultsList[1].Url);
+        }
+
+        /// <summary>
+        /// Test sending and recieving messages via text/json
+        /// </summary>
+        [Test]
+        public void TestClientServerWithXmlFormat()
+        {
+            ExampleHttpServer server = new ExampleHttpServer(new ExampleSearchImpl());
+            //obviously if this was a 'real' transport we would not use the server, rather the server would be listening, the client transmitting
+            IHttpTransfer wire = server;
+
+            ISearchService client = new SearchService(new ExampleClient(wire, "text/xml"));
+            //now the client has a real, typed, interface to work with:
+            SearchResponse result = client.Search(SearchRequest.CreateBuilder().AddCriteria("Test").Build());
+            Assert.AreEqual(1, result.ResultsCount);
+            Assert.AreEqual("Test", result.ResultsList[0].Name);
+            Assert.AreEqual("http://search.com", result.ResultsList[0].Url);
+
+            //The test part of this, call the only other method
+            result =
+                client.RefineSearch(
+                    RefineSearchRequest.CreateBuilder().SetPreviousResults(result).AddCriteria("Refine").Build());
+            Assert.AreEqual(2, result.ResultsCount);
+            Assert.AreEqual("Test", result.ResultsList[0].Name);
+            Assert.AreEqual("http://search.com", result.ResultsList[0].Url);
+
+            Assert.AreEqual("Refine", result.ResultsList[1].Name);
+            Assert.AreEqual("http://refine.com", result.ResultsList[1].Url);
+        }
+
+        /// <summary>
+        /// Test sending and recieving messages via text/json
+        /// </summary>
+        [Test]
+        public void TestClientServerWithProtoFormat()
+        {
+            ExampleHttpServer server = new ExampleHttpServer(new ExampleSearchImpl());
+            //obviously if this was a 'real' transport we would not use the server, rather the server would be listening, the client transmitting
+            IHttpTransfer wire = server;
+
+            ISearchService client = new SearchService(new ExampleClient(wire, "application/x-protobuf"));
+            //now the client has a real, typed, interface to work with:
+            SearchResponse result = client.Search(SearchRequest.CreateBuilder().AddCriteria("Test").Build());
+            Assert.AreEqual(1, result.ResultsCount);
+            Assert.AreEqual("Test", result.ResultsList[0].Name);
+            Assert.AreEqual("http://search.com", result.ResultsList[0].Url);
+
+            //The test part of this, call the only other method
+            result =
+                client.RefineSearch(
+                    RefineSearchRequest.CreateBuilder().SetPreviousResults(result).AddCriteria("Refine").Build());
+            Assert.AreEqual(2, result.ResultsCount);
+            Assert.AreEqual("Test", result.ResultsList[0].Name);
+            Assert.AreEqual("http://search.com", result.ResultsList[0].Url);
+
+            Assert.AreEqual("Refine", result.ResultsList[1].Name);
+            Assert.AreEqual("http://refine.com", result.ResultsList[1].Url);
+        }
+
+        /// <summary>
+        /// Test sending and recieving messages via text/json
+        /// </summary>
+        [Test]
+        public void TestClientServerWithCustomFormat()
+        {
+            ExampleHttpServer server = new ExampleHttpServer(new ExampleSearchImpl());
+            //Setup our custom mime-type format as the only format supported:
+            server.Options.MimeInputTypes.Clear();
+            server.Options.MimeInputTypes.Add("foo/bar", CodedInputStream.CreateInstance);
+            server.Options.MimeOutputTypes.Clear();
+            server.Options.MimeOutputTypes.Add("foo/bar", CodedOutputStream.CreateInstance);
+
+            //obviously if this was a 'real' transport we would not use the server, rather the server would be listening, the client transmitting
+            IHttpTransfer wire = server;
+
+            ExampleClient exclient = new ExampleClient(wire, "foo/bar");
+            //Add our custom mime-type format
+            exclient.Options.MimeInputTypes.Add("foo/bar", CodedInputStream.CreateInstance);
+            exclient.Options.MimeOutputTypes.Add("foo/bar", CodedOutputStream.CreateInstance);
+            ISearchService client = new SearchService(exclient);
+
+            //now the client has a real, typed, interface to work with:
+            SearchResponse result = client.Search(SearchRequest.CreateBuilder().AddCriteria("Test").Build());
+            Assert.AreEqual(1, result.ResultsCount);
+            Assert.AreEqual("Test", result.ResultsList[0].Name);
+            Assert.AreEqual("http://search.com", result.ResultsList[0].Url);
+
+            //The test part of this, call the only other method
+            result =
+                client.RefineSearch(
+                    RefineSearchRequest.CreateBuilder().SetPreviousResults(result).AddCriteria("Refine").Build());
+            Assert.AreEqual(2, result.ResultsCount);
+            Assert.AreEqual("Test", result.ResultsList[0].Name);
+            Assert.AreEqual("http://search.com", result.ResultsList[0].Url);
+
+            Assert.AreEqual("Refine", result.ResultsList[1].Name);
+            Assert.AreEqual("http://refine.com", result.ResultsList[1].Url);
+        }
+
+        /// <summary>
+        /// Test sending and recieving messages via text/json
+        /// </summary>
+        [Test]
+        public void TestServerWithUriFormat()
+        {
+            ExampleHttpServer server = new ExampleHttpServer(new ExampleSearchImpl());
+            //obviously if this was a 'real' transport we would not use the server, rather the server would be listening, the client transmitting
+            IHttpTransfer wire = server;
+
+            MemoryStream input = new MemoryStream(Encoding.UTF8.GetBytes("?Criteria=Test&Criteria=Test+of%20URI"));
+            MemoryStream output = new MemoryStream();
+
+            //Call the server
+            wire.Execute("Search",
+                         MessageFormatOptions.ContentFormUrlEncoded, input,
+                         MessageFormatOptions.ContentTypeProtoBuffer, output
+                         );
+
+            SearchResponse result = SearchResponse.ParseFrom(output.ToArray());
+            Assert.AreEqual(2, result.ResultsCount);
+            Assert.AreEqual("Test", result.ResultsList[0].Name);
+            Assert.AreEqual("http://search.com", result.ResultsList[0].Url);
+
+            Assert.AreEqual("Test of URI", result.ResultsList[1].Name);
+            Assert.AreEqual("http://search.com", result.ResultsList[1].Url);
+        }
+
+        /// <summary>
+        /// Test sending and recieving messages via text/json
+        /// </summary>
+        [Test, ExpectedException(typeof(ArgumentOutOfRangeException))]
+        public void TestInvalidMimeType()
+        {
+            ExampleHttpServer server = new ExampleHttpServer(new ExampleSearchImpl());
+            //obviously if this was a 'real' transport we would not use the server, rather the server would be listening, the client transmitting
+            IHttpTransfer wire = server;
+
+            MemoryStream input = new MemoryStream();
+            MemoryStream output = new MemoryStream();
+
+            //Call the server
+            wire.Execute("Search",
+                         "bad/mime", input,
+                         MessageFormatOptions.ContentTypeProtoBuffer, output
+                         );
+            Assert.Fail();
+        }
+
+        /// <summary>
+        /// Test sending and recieving messages via text/json
+        /// </summary>
+        [Test]
+        public void TestDefaultMimeType()
+        {
+            ExampleHttpServer server = new ExampleHttpServer(new ExampleSearchImpl());
+            
+            //obviously if this was a 'real' transport we would not use the server, rather the server would be listening, the client transmitting
+            IHttpTransfer wire = server;
+
+
+            MemoryStream input = new MemoryStream(new SearchRequest.Builder().AddCriteria("Test").Build().ToByteArray());
+            MemoryStream output = new MemoryStream();
+
+            //With this default set, any invalid/unknown mime-type will be mapped to use that format
+            server.Options.DefaultContentType = MessageFormatOptions.ContentTypeProtoBuffer;
+
+            wire.Execute("Search",
+                         "foo", input,
+                         "bar", output
+                         );
+
+            SearchResponse result = SearchResponse.ParseFrom(output.ToArray());
+            Assert.AreEqual(1, result.ResultsCount);
+            Assert.AreEqual("Test", result.ResultsList[0].Name);
+            Assert.AreEqual("http://search.com", result.ResultsList[0].Url);
+        }
+    }
+}

+ 171 - 0
src/ProtocolBuffersLite.Test/TestRpcGenerator.cs

@@ -0,0 +1,171 @@
+#region Copyright notice and license
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using Google.ProtocolBuffers;
+using Google.ProtocolBuffers.TestProtos;
+using NUnit.Framework;
+
+namespace Google.ProtocolBuffers
+{
+    /// <summary>
+    /// This class verifies the correct code is generated from unittest_rpc_interop.proto and provides a small demonstration
+    /// of using the new IRpcDispatch to write a client/server
+    /// </summary>
+    [TestFixture]
+    public class TestRpcGenerator
+    {
+        /// <summary>
+        /// A sample implementation of the ISearchService for testing
+        /// </summary>
+        private class ExampleSearchImpl : ISearchService
+        {
+            SearchResponse ISearchService.Search(SearchRequest searchRequest)
+            {
+                if (searchRequest.CriteriaCount == 0)
+                {
+                    throw new ArgumentException("No criteria specified.", new InvalidOperationException());
+                }
+                SearchResponse.Builder resp = SearchResponse.CreateBuilder();
+                foreach (string criteria in searchRequest.CriteriaList)
+                {
+                    resp.AddResults(
+                        SearchResponse.Types.ResultItem.CreateBuilder().SetName(criteria).SetUrl("http://search.com").
+                            Build());
+                }
+                return resp.Build();
+            }
+
+            SearchResponse ISearchService.RefineSearch(RefineSearchRequest refineSearchRequest)
+            {
+                SearchResponse.Builder resp = refineSearchRequest.PreviousResults.ToBuilder();
+                foreach (string criteria in refineSearchRequest.CriteriaList)
+                {
+                    resp.AddResults(
+                        SearchResponse.Types.ResultItem.CreateBuilder().SetName(criteria).SetUrl("http://refine.com").
+                            Build());
+                }
+                return resp.Build();
+            }
+        }
+
+        /// <summary>
+        /// An example extraction of the wire protocol
+        /// </summary>
+        private interface IWireTransfer
+        {
+            byte[] Execute(string method, byte[] message);
+        }
+
+        /// <summary>
+        /// An example of a server responding to a wire request
+        /// </summary>
+        private class ExampleServerHost : IWireTransfer
+        {
+            private readonly IRpcServerStub _stub;
+
+            public ExampleServerHost(ISearchService implementation)
+            {
+                //on the server, we create a dispatch to call the appropriate method by name
+                IRpcDispatch dispatch = new SearchService.Dispatch(implementation);
+                //we then wrap that dispatch in a server stub which will deserialize the wire bytes to the message
+                //type appropriate for the method name being invoked.
+                _stub = new SearchService.ServerStub(dispatch);
+            }
+
+            byte[] IWireTransfer.Execute(string method, byte[] message)
+            {
+                //now when we recieve a wire transmission to invoke a method by name with a byte[] or stream payload
+                //we just simply call the sub:
+                IMessageLite response = _stub.CallMethod(method, CodedInputStream.CreateInstance(message),
+                                                         ExtensionRegistry.Empty);
+                //now we return the expected response message:
+                return response.ToByteArray();
+            }
+        }
+
+        /// <summary>
+        /// An example of a client sending a wire request
+        /// </summary>
+        private class ExampleClient : IRpcDispatch
+        {
+            private readonly IWireTransfer _wire;
+
+            public ExampleClient(IWireTransfer wire)
+            {
+                _wire = wire;
+            }
+
+            TMessage IRpcDispatch.CallMethod<TMessage, TBuilder>(string method, IMessageLite request,
+                                                                 IBuilderLite<TMessage, TBuilder> response)
+            {
+                byte[] rawResponse = _wire.Execute(method, request.ToByteArray());
+                response.MergeFrom(rawResponse);
+                return response.Build();
+            }
+        }
+
+        /// <summary>
+        /// Put it all together to create one seamless client/server experience full of rich-type goodness ;)
+        /// All you need to do is send/recieve the method name and message bytes across the wire.
+        /// </summary>
+        [Test]
+        public void TestClientServerDispatch()
+        {
+            ExampleServerHost server = new ExampleServerHost(new ExampleSearchImpl());
+            //obviously if this was a 'real' transport we would not use the server, rather the server would be listening, the client transmitting
+            IWireTransfer wire = server;
+
+            ISearchService client = new SearchService(new ExampleClient(wire));
+            //now the client has a real, typed, interface to work with:
+            SearchResponse result = client.Search(SearchRequest.CreateBuilder().AddCriteria("Test").Build());
+            Assert.AreEqual(1, result.ResultsCount);
+            Assert.AreEqual("Test", result.ResultsList[0].Name);
+            Assert.AreEqual("http://search.com", result.ResultsList[0].Url);
+
+            //The test part of this, call the only other method
+            result =
+                client.RefineSearch(
+                    RefineSearchRequest.CreateBuilder().SetPreviousResults(result).AddCriteria("Refine").Build());
+            Assert.AreEqual(2, result.ResultsCount);
+            Assert.AreEqual("Test", result.ResultsList[0].Name);
+            Assert.AreEqual("http://search.com", result.ResultsList[0].Url);
+
+            Assert.AreEqual("Refine", result.ResultsList[1].Name);
+            Assert.AreEqual("http://refine.com", result.ResultsList[1].Url);
+        }
+    }
+}

+ 24 - 0
src/copysolution.bat

@@ -0,0 +1,24 @@
+@ECHO OFF
+IF "%1" == "2008" GOTO COPY2008
+IF "%1" == "2010" GOTO COPY2010
+GOTO HELP
+
+:COPY2008
+type ProtocolBuffers.sln | FIND " Visual Studio " > Temp.sln
+type ProtocolBuffers2008.sln | FIND /V " Visual Studio " >> Temp.sln
+move /Y Temp.sln ProtocolBuffers.sln
+GOTO EXIT
+
+:COPY2010
+type ProtocolBuffers2008.sln | FIND " Visual Studio " > Temp.sln
+type ProtocolBuffers.sln | FIND /V " Visual Studio " >> Temp.sln
+move /Y Temp.sln ProtocolBuffers2008.sln
+GOTO EXIT
+
+:HELP
+ECHO.
+ECHO Specify the Visiual Studio edition (2008/2010)
+ECHO Example:  %~nx0 2008
+ECHO.
+
+:EXIT