csharptest 14 lat temu
rodzic
commit
7f7a7547bb
93 zmienionych plików z 9541 dodań i 1838 usunięć
  1. 92 0
      CHANGES.txt
  2. 9 9
      build/Build.bat
  3. 41 41
      build/BuildAll.bat
  4. 4 4
      build/BuildSilverlight2.bat
  5. 18 18
      build/GenerateCompletePackage.bat
  6. 12 12
      build/GenerateReleasePackage.bat
  7. 4 4
      build/RunBenchmarks.bat
  8. 8 8
      build/build35.bat
  9. 31 31
      license.txt
  10. 21 23
      protos/extest/unittest_extras_xmltest.proto
  11. 44 0
      protos/extest/unittest_issues.proto
  12. 44 0
      protos/npp.language.xml
  13. 0 40
      readme.txt
  14. 169 48
      src/AddressBook/AddressBookProtos.cs
  15. 6 6
      src/ProtoGen.Test/DependencyResolutionTest.cs
  16. 8 3
      src/ProtoGen/EnumFieldGenerator.cs
  17. 19 0
      src/ProtoGen/FieldGeneratorBase.cs
  18. 15 3
      src/ProtoGen/MessageFieldGenerator.cs
  19. 57 18
      src/ProtoGen/MessageGenerator.cs
  20. 8 3
      src/ProtoGen/PrimitiveFieldGenerator.cs
  21. 18 4
      src/ProtoGen/RepeatedEnumFieldGenerator.cs
  22. 22 4
      src/ProtoGen/RepeatedMessageFieldGenerator.cs
  23. 18 11
      src/ProtoGen/RepeatedPrimitiveFieldGenerator.cs
  24. 2 2
      src/ProtoGen/UmbrellaClassGenerator.cs
  25. 10 6
      src/ProtocolBuffers.Serialization/AbstractReader.cs
  26. 0 4
      src/ProtocolBuffers.Serialization/AbstractTextReader.cs
  27. 19 16
      src/ProtocolBuffers.Serialization/AbstractWriter.cs
  28. 13 1
      src/ProtocolBuffers.Serialization/DictionaryReader.cs
  29. 14 1
      src/ProtocolBuffers.Serialization/DictionaryWriter.cs
  30. 162 0
      src/ProtocolBuffers.Serialization/Http/FormUrlEncodedReader.cs
  31. 153 0
      src/ProtocolBuffers.Serialization/Http/MessageFormatFactory.cs
  32. 167 0
      src/ProtocolBuffers.Serialization/Http/MessageFormatOptions.cs
  33. 34 0
      src/ProtocolBuffers.Serialization/Http/ServiceExtensions.cs
  34. 22 5
      src/ProtocolBuffers.Serialization/JsonFormatReader.cs
  35. 24 4
      src/ProtocolBuffers.Serialization/JsonFormatWriter.cs
  36. 4 0
      src/ProtocolBuffers.Serialization/ProtocolBuffers.Serialization.csproj
  37. 92 53
      src/ProtocolBuffers.Serialization/XmlFormatReader.cs
  38. 57 20
      src/ProtocolBuffers.Serialization/XmlFormatWriter.cs
  39. 73 0
      src/ProtocolBuffers.Test/CodedInputStreamTest.cs
  40. 79 0
      src/ProtocolBuffers.Test/CodedOutputStreamTest.cs
  41. 59 0
      src/ProtocolBuffers.Test/Collections/PopsicleListTest.cs
  42. 18 0
      src/ProtocolBuffers.Test/Compatibility/JsonCompatibilityTests.cs
  43. 21 0
      src/ProtocolBuffers.Test/Compatibility/XmlCompatibilityTests.cs
  44. 102 0
      src/ProtocolBuffers.Test/DeprecatedMemberTest.cs
  45. 123 0
      src/ProtocolBuffers.Test/GeneratedBuilderTest.cs
  46. 0 16
      src/ProtocolBuffers.Test/GeneratedMessageTest.cs
  47. 1 1
      src/ProtocolBuffers.Test/Properties/AssemblyInfo.cs
  48. 7 4
      src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj
  49. 170 0
      src/ProtocolBuffers.Test/ReusableBuilderTest.cs
  50. 36 12
      src/ProtocolBuffers.Test/SerializableTest.cs
  51. 38 0
      src/ProtocolBuffers.Test/TestCornerCases.cs
  52. 264 0
      src/ProtocolBuffers.Test/TestMimeMessageFormats.cs
  53. 53 14
      src/ProtocolBuffers.Test/TestProtos/UnitTestCSharpOptionsProtoFile.cs
  54. 371 105
      src/ProtocolBuffers.Test/TestProtos/UnitTestCustomOptionsProtoFile.cs
  55. 64 21
      src/ProtocolBuffers.Test/TestProtos/UnitTestEmbedOptimizeForProtoFile.cs
  56. 1 1
      src/ProtocolBuffers.Test/TestProtos/UnitTestEmptyProtoFile.cs
  57. 2174 56
      src/ProtocolBuffers.Test/TestProtos/UnitTestExtrasIssuesProtoFile.cs
  58. 1 1
      src/ProtocolBuffers.Test/TestProtos/UnitTestGenericServices.cs
  59. 203 33
      src/ProtocolBuffers.Test/TestProtos/UnitTestGoogleSizeProtoFile.cs
  60. 202 34
      src/ProtocolBuffers.Test/TestProtos/UnitTestGoogleSpeedProtoFile.cs
  61. 49 14
      src/ProtocolBuffers.Test/TestProtos/UnitTestImportLiteProtoFile.cs
  62. 49 14
      src/ProtocolBuffers.Test/TestProtos/UnitTestImportProtoFile.cs
  63. 302 86
      src/ProtocolBuffers.Test/TestProtos/UnitTestMessageSetProtoFile.cs
  64. 49 14
      src/ProtocolBuffers.Test/TestProtos/UnitTestNoGenericServicesProtoFile.cs
  65. 151 46
      src/ProtocolBuffers.Test/TestProtos/UnitTestOptimizeForProtoFile.cs
  66. 286 111
      src/ProtocolBuffers.Test/TestProtos/UnitTestProtoFile.cs
  67. 222 68
      src/ProtocolBuffers.Test/TestProtos/UnitTestRpcInterop.cs
  68. 299 93
      src/ProtocolBuffers.Test/TestProtos/UnitTestXmlSerializerTestProtoFile.cs
  69. 84 0
      src/ProtocolBuffers.Test/TestReaderForUrlEncoded.cs
  70. 386 0
      src/ProtocolBuffers.Test/TestRpcForMimeTypes.cs
  71. 86 0
      src/ProtocolBuffers.Test/TestWriterFormatJson.cs
  72. 119 2
      src/ProtocolBuffers.Test/TestWriterFormatXml.cs
  73. 3 0
      src/ProtocolBuffers/CodedInputStream.cs
  74. 2 2
      src/ProtocolBuffers/CodedOutputStream.ComputeSize.cs
  75. 5 2
      src/ProtocolBuffers/CodedOutputStream.cs
  76. 33 5
      src/ProtocolBuffers/Collections/PopsicleList.cs
  77. 12 10
      src/ProtocolBuffers/CustomSerialization.cs
  78. 219 53
      src/ProtocolBuffers/DescriptorProtos/CSharpOptions.cs
  79. 281 95
      src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs
  80. 3 34
      src/ProtocolBuffers/GeneratedBuilder.cs
  81. 1 32
      src/ProtocolBuffers/GeneratedBuilderLite.cs
  82. 18 0
      src/ProtocolBuffers/ICodedInputStream.cs
  83. 18 0
      src/ProtocolBuffers/ICodedOutputStream.cs
  84. 1 1
      src/ProtocolBuffers/IRpcController.cs
  85. 26 2
      src/ProtocolBuffers/IRpcDispatch.cs
  86. 327 93
      src/ProtocolBuffersLite.Test/TestProtos/UnitTestExtrasFullProtoFile.cs
  87. 285 78
      src/ProtocolBuffersLite.Test/TestProtos/UnitTestExtrasLiteProtoFile.cs
  88. 49 14
      src/ProtocolBuffersLite.Test/TestProtos/UnitTestImportLiteProtoFile.cs
  89. 49 14
      src/ProtocolBuffersLite.Test/TestProtos/UnitTestImportProtoFile.cs
  90. 54 17
      src/ProtocolBuffersLite.Test/TestProtos/UnitTestLiteImportNonLiteProtoFile.cs
  91. 286 111
      src/ProtocolBuffersLite.Test/TestProtos/UnitTestLiteProtoFile.cs
  92. 286 111
      src/ProtocolBuffersLite.Test/TestProtos/UnitTestProtoFile.cs
  93. 0 16
      todo.txt

+ 92 - 0
CHANGES.txt

@@ -0,0 +1,92 @@
+===============================================================================
+Welcome to the C# port of Google Protocol Buffers, written by Jon Skeet
+(skeet@pobox.com) based on the work of many talented people.
+
+For more information about this port, visit its homepage:
+http://protobuf-csharp-port.googlecode.com
+
+For more information about Protocol Buffers in general, visit the project page 
+for the C++, Java and Python project:
+http://protobuf.googlecode.com
+===============================================================================
+RELEASE NOTES - Version TBD
+===============================================================================
+
+(PENDING MERGE)
+- Issue 20:	Support for decorating classes [Serializable]
+- Issue 22:	Reusable Builder classes
+- Issue 24:	Support for using Json/Xml formats with ICodedInputStream
+
+Features:
+- Added option service_generator_type to control service generation with
+  NONE, GENERIC, INTERFACE, or IRPCDISPATCH
+- Added interfaces IRpcDispatch and IRpcServerStub to provide for blocking
+  services and implementations.
+- Added ProtoGen.exe command-line argument "--protoc_dir=" to specify the 
+  location of protoc.exe.
+- Extracted interfaces for ICodedInputStream and ICodedOutputStream to allow
+  custom implementation of writers with both speed and size optimizations.
+- Addition of the "Google.ProtoBuffers.Serialization" assembly to support
+  reading and writing messages to/from XML, JSON, IDictionary<,> and others.
+- Several performance related fixes and tweeks
+- Issue 3:	Add option to mark generated code with attribute
+- Issue 21:	Decorate fields with [deprecated=true] as [System.Obsolete]
+
+Fixes:
+- Issue 13:	Message with Field same name as message causes uncompilable .cs
+- Issue 16:	Does not integrate well with other tooling
+- Issue 19:	Support for negative enum values
+- Issue 26:	AddRange in GeneratedBuilder iterates twice.
+- Issue 27:	Remove XML documentation output from test projects to clear 
+  warnings/errors.
+- Big-endian support for float, and double on Silverlight
+- Packed and Unpacked parsing allow for all repeated, as per version 2.3
+- Fix for leaving Builder a public ctor on internal classes for use with
+  generic "where T: new()" constraints.
+
+Other:
+- Reformatted all code and line-endings to C# defaults
+- Reworking of performance benchmarks to produce reliable results, option /v2
+
+===============================================================================
+RELEASE NOTES - Version 2.3.0.277
+===============================================================================
+
+Features:
+- Added cls_compliance option to generate attributes indicating 
+  non-CLS-compliance.
+- Added file_extension option to control the generated output file's extension.
+- Added umbrella_namespace option to place the umbrella class into a nested
+  namespace to address issues with proto files having the same name as a 
+  message it contains.
+- Added output_directory option to set the output path for the source file(s).
+- Added ignore_google_protobuf option to avoid generating code for includes 
+  from the google.protobuf package.
+- Added the LITE framework (Google.ProtoBuffersLite.dll) and the ability to
+  generate code with "option optimize_for = LITE_RUNTIME;".
+- Added ability to invoke protoc.exe from within ProtoGen.exe.
+- Upgraded to protoc.exe (2.3) compiler.
+
+Fixes:
+- Issue 9:	Class cannot be static and sealed error
+- Issue 12:	default value for enumerate fields must be filled out
+
+Other:
+- Rewrite of build using MSBbuild instead of NAnt
+- Moved to NUnit Version 2.2.8.0
+- Changed to using secure .snk for releases
+
+===============================================================================
+RELEASE NOTES - Version 0.9.1
+===============================================================================
+
+Fixes:
+- issue 10:	Incorrect encoding of packed fields when serialized
+
+===============================================================================
+RELEASE NOTES - Version 0.9.0
+===============================================================================
+
+- Initial release
+
+===============================================================================

+ 9 - 9
build/Build.bat

@@ -1,10 +1,10 @@
-@echo off
-SET BUILD_TARGET=%1
-SET BUILD_CONFIG=%2
-
-IF "%BUILD_TARGET%"=="" SET BUILD_TARGET=Rebuild
-IF "%BUILD_CONFIG%"=="" SET BUILD_CONFIG=Debug
-
-CMD.exe /Q /C "CD %~dp0 && %WINDIR%\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe build.csproj %3 %4 %5 %6 /t:%BUILD_TARGET% /p:BuildConfiguration=%BUILD_CONFIG% /p:Platform="Any CPU" /p:BuildTools=4.0 /toolsversion:4.0"
-
+@echo off
+SET BUILD_TARGET=%1
+SET BUILD_CONFIG=%2
+
+IF "%BUILD_TARGET%"=="" SET BUILD_TARGET=Rebuild
+IF "%BUILD_CONFIG%"=="" SET BUILD_CONFIG=Debug
+
+CMD.exe /Q /C "CD %~dp0 && %WINDIR%\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe build.csproj %3 %4 %5 %6 /t:%BUILD_TARGET% /p:BuildConfiguration=%BUILD_CONFIG% /p:Platform="Any CPU" /p:BuildTools=4.0 /toolsversion:4.0"
+
 pause

+ 41 - 41
build/BuildAll.bat

@@ -1,42 +1,42 @@
-@ECHO OFF
-
-SET PREV_WORKING_DIR=%CD%
-CD %~dp0
-
-REM -- 3.5 Debug build, ensure this continues to work
-%WINDIR%\Microsoft.NET\Framework\v3.5\MSBuild.exe build.csproj /t:Rebuild /p:BuildConfiguration=Debug /p:Platform="Any CPU" /p:BuildTools=3.5 /toolsversion:3.5"
-IF ERRORLEVEL 1 GOTO ERROR
-
-REM -- 4.0 Debug build
-%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild build.csproj /m /t:Rebuild /p:BuildConfiguration=Debug /p:Platform="Any CPU"
-IF ERRORLEVEL 1 GOTO ERROR
-
-REM -- 4.0 Release build
-%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild build.csproj /m /t:Rebuild /p:BuildConfiguration=Release /p:Platform="Any CPU"
-IF ERRORLEVEL 1 GOTO ERROR
-
-IF EXIST "%ProgramFiles%\MSBuild\Microsoft\Silverlight\v2.0\Microsoft.Silverlight.CSharp.targets" GOTO SILVERLIGHT
-IF EXIST "%ProgramFiles(x86)%\MSBuild\Microsoft\Silverlight\v2.0\Microsoft.Silverlight.CSharp.targets" GOTO SILVERLIGHT
-
-ECHO Unable to locate %ProgramFiles(x86)%\MSBuild\Microsoft\Silverlight\v2.0
-GOTO ERROR
-
-:SILVERLIGHT
-
-REM -- 4.0 Debug_Silverlight2 build
-%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild build.csproj /m /t:Rebuild /p:BuildConfiguration=Debug_Silverlight2 /p:Platform="Any CPU"
-IF ERRORLEVEL 1 GOTO ERROR
-
-REM -- 4.0 Release_Silverlight2 build
-%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild build.csproj /m /t:Rebuild /p:BuildConfiguration=Release_Silverlight2 /p:Platform="Any CPU"
-IF ERRORLEVEL 1 GOTO ERROR
-
-GOTO END
-
-:ERROR
-CD %PREV_WORKING_DIR%
-PAUSE
-
-:END
-CD %PREV_WORKING_DIR%
+@ECHO OFF
+
+SET PREV_WORKING_DIR=%CD%
+CD %~dp0
+
+REM -- 3.5 Debug build, ensure this continues to work
+%WINDIR%\Microsoft.NET\Framework\v3.5\MSBuild.exe build.csproj /t:Rebuild /p:BuildConfiguration=Debug /p:Platform="Any CPU" /p:BuildTools=3.5 /toolsversion:3.5"
+IF ERRORLEVEL 1 GOTO ERROR
+
+REM -- 4.0 Debug build
+%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild build.csproj /m /t:Rebuild /p:BuildConfiguration=Debug /p:Platform="Any CPU"
+IF ERRORLEVEL 1 GOTO ERROR
+
+REM -- 4.0 Release build
+%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild build.csproj /m /t:Rebuild /p:BuildConfiguration=Release /p:Platform="Any CPU"
+IF ERRORLEVEL 1 GOTO ERROR
+
+IF EXIST "%ProgramFiles%\MSBuild\Microsoft\Silverlight\v2.0\Microsoft.Silverlight.CSharp.targets" GOTO SILVERLIGHT
+IF EXIST "%ProgramFiles(x86)%\MSBuild\Microsoft\Silverlight\v2.0\Microsoft.Silverlight.CSharp.targets" GOTO SILVERLIGHT
+
+ECHO Unable to locate %ProgramFiles(x86)%\MSBuild\Microsoft\Silverlight\v2.0
+GOTO ERROR
+
+:SILVERLIGHT
+
+REM -- 4.0 Debug_Silverlight2 build
+%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild build.csproj /m /t:Rebuild /p:BuildConfiguration=Debug_Silverlight2 /p:Platform="Any CPU"
+IF ERRORLEVEL 1 GOTO ERROR
+
+REM -- 4.0 Release_Silverlight2 build
+%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild build.csproj /m /t:Rebuild /p:BuildConfiguration=Release_Silverlight2 /p:Platform="Any CPU"
+IF ERRORLEVEL 1 GOTO ERROR
+
+GOTO END
+
+:ERROR
+CD %PREV_WORKING_DIR%
+PAUSE
+
+:END
+CD %PREV_WORKING_DIR%
 SET PREV_WORKING_DIR=

+ 4 - 4
build/BuildSilverlight2.bat

@@ -1,5 +1,5 @@
-@echo off
-
-%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild build.csproj /m /t:Build /p:BuildConfiguration=Debug_Silverlight2 /p:Platform="Any CPU"
-
+@echo off
+
+%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild build.csproj /m /t:Build /p:BuildConfiguration=Debug_Silverlight2 /p:Platform="Any CPU"
+
 pause

+ 18 - 18
build/GenerateCompletePackage.bat

@@ -1,19 +1,19 @@
-@ECHO OFF
-%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild build.csproj /m /t:PrepareOutputDirectory
-IF ERRORLEVEL 1 GOTO END
-
-%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild build.csproj /m /t:Rebuild;PreparePackageComponent /p:BuildConfiguration=Debug /p:Platform="Any CPU" %PROTOBUF_KEY_FILE%
-IF ERRORLEVEL 1 GOTO END
-
-%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild build.csproj /m /t:Rebuild;PreparePackageComponent /p:BuildConfiguration=Debug_Silverlight2 /p:Platform="Any CPU" %PROTOBUF_KEY_FILE%
-IF ERRORLEVEL 1 GOTO END
-
-%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild build.csproj /m /t:Rebuild;PreparePackageComponent /p:BuildConfiguration=Release /p:Platform="Any CPU" %PROTOBUF_KEY_FILE%
-IF ERRORLEVEL 1 GOTO END
-
-%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild build.csproj /m /t:Rebuild;PreparePackageComponent /p:BuildConfiguration=Release_Silverlight2 /p:Platform="Any CPU" %PROTOBUF_KEY_FILE%
-IF ERRORLEVEL 1 GOTO END
-
-%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild build.csproj /m /t:GeneratePackage /p:PackageName=AllBinariesAndSource.zip /p:Platform="Any CPU"
-
+@ECHO OFF
+%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild build.csproj /m /t:PrepareOutputDirectory
+IF ERRORLEVEL 1 GOTO END
+
+%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild build.csproj /m /t:Rebuild;PreparePackageComponent /p:BuildConfiguration=Debug /p:Platform="Any CPU" %PROTOBUF_KEY_FILE%
+IF ERRORLEVEL 1 GOTO END
+
+%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild build.csproj /m /t:Rebuild;PreparePackageComponent /p:BuildConfiguration=Debug_Silverlight2 /p:Platform="Any CPU" %PROTOBUF_KEY_FILE%
+IF ERRORLEVEL 1 GOTO END
+
+%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild build.csproj /m /t:Rebuild;PreparePackageComponent /p:BuildConfiguration=Release /p:Platform="Any CPU" %PROTOBUF_KEY_FILE%
+IF ERRORLEVEL 1 GOTO END
+
+%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild build.csproj /m /t:Rebuild;PreparePackageComponent /p:BuildConfiguration=Release_Silverlight2 /p:Platform="Any CPU" %PROTOBUF_KEY_FILE%
+IF ERRORLEVEL 1 GOTO END
+
+%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild build.csproj /m /t:GeneratePackage /p:PackageName=AllBinariesAndSource.zip /p:Platform="Any CPU"
+
 :END

+ 12 - 12
build/GenerateReleasePackage.bat

@@ -1,13 +1,13 @@
-@ECHO OFF
-%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild build.csproj /m /t:PrepareOutputDirectory
-IF ERRORLEVEL 1 GOTO END
-
-%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild build.csproj /m /t:Rebuild;PreparePackageComponent /p:BuildConfiguration=Release /p:Platform="Any CPU" %PROTOBUF_KEY_FILE%
-IF ERRORLEVEL 1 GOTO END
-
-%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild build.csproj /m /t:Rebuild;PreparePackageComponent /p:BuildConfiguration=Release_Silverlight2 /p:Platform="Any CPU" %PROTOBUF_KEY_FILE%
-IF ERRORLEVEL 1 GOTO END
-
-%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild build.csproj /m /t:GeneratePackage /p:PackageName=ReleaseBinaries.zip /p:Platform="Any CPU"
-
+@ECHO OFF
+%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild build.csproj /m /t:PrepareOutputDirectory
+IF ERRORLEVEL 1 GOTO END
+
+%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild build.csproj /m /t:Rebuild;PreparePackageComponent /p:BuildConfiguration=Release /p:Platform="Any CPU" %PROTOBUF_KEY_FILE%
+IF ERRORLEVEL 1 GOTO END
+
+%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild build.csproj /m /t:Rebuild;PreparePackageComponent /p:BuildConfiguration=Release_Silverlight2 /p:Platform="Any CPU" %PROTOBUF_KEY_FILE%
+IF ERRORLEVEL 1 GOTO END
+
+%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild build.csproj /m /t:GeneratePackage /p:PackageName=ReleaseBinaries.zip /p:Platform="Any CPU"
+
 :END

+ 4 - 4
build/RunBenchmarks.bat

@@ -1,5 +1,5 @@
-@echo off
-
-%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild %~dp0\build.csproj /m /t:RunBenchmarks /p:BuildConfiguration=Release /p:Platform="Any CPU"
-
+@echo off
+
+%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild %~dp0\build.csproj /m /t:RunBenchmarks /p:BuildConfiguration=Release /p:Platform="Any CPU"
+
 pause

+ 8 - 8
build/build35.bat

@@ -1,8 +1,8 @@
-@echo off
-SET BUILD_TARGET=%1
-SET BUILD_CONFIG=%2
-
-IF "%BUILD_TARGET%"=="" SET BUILD_TARGET=Rebuild
-IF "%BUILD_CONFIG%"=="" SET BUILD_CONFIG=Debug
-
-CMD.exe /Q /C "CD %~dp0 && %WINDIR%\Microsoft.NET\Framework\v3.5\MSBuild.exe build.csproj %3 %4 %5 %6 /t:%BUILD_TARGET% /p:BuildConfiguration=%BUILD_CONFIG% /p:Platform="Any CPU" /p:BuildTools=3.5 /toolsversion:3.5"
+@echo off
+SET BUILD_TARGET=%1
+SET BUILD_CONFIG=%2
+
+IF "%BUILD_TARGET%"=="" SET BUILD_TARGET=Rebuild
+IF "%BUILD_CONFIG%"=="" SET BUILD_CONFIG=Debug
+
+CMD.exe /Q /C "CD %~dp0 && %WINDIR%\Microsoft.NET\Framework\v3.5\MSBuild.exe build.csproj %3 %4 %5 %6 /t:%BUILD_TARGET% /p:BuildConfiguration=%BUILD_CONFIG% /p:Platform="Any CPU" /p:BuildTools=3.5 /toolsversion:3.5"

+ 31 - 31
license.txt

@@ -1,31 +1,31 @@
-Protocol Buffers - Google's data interchange format
-Copyright 2008-2010 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.
+Protocol Buffers - Google's data interchange format
+Copyright 2008-2010 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.

+ 21 - 23
protos/extest/unittest_extras_xmltest.proto

@@ -8,46 +8,44 @@ package protobuf_unittest_extra;
 option optimize_for = SPEED;
 
 enum EnumOptions {
-    ONE = 0;
-    TWO = 1;
-    THREE = 2;
+  ONE = 0;
+  TWO = 1;
+  THREE = 2;
 }
 
-message TestXmlChild
-{
-    repeated EnumOptions options = 3;
-    optional bytes binary = 4;
+message TestXmlChild {
+  repeated EnumOptions options = 3;
+  optional bytes binary = 4;
 }
 
 message TestXmlNoFields {
 }
 
 message TestXmlRescursive {
-    optional TestXmlRescursive child = 1;
+  optional TestXmlRescursive child = 1;
 }
 
 message TestXmlMessage {
 
-    optional int64 number = 6;
-    repeated int32 numbers = 2;
-    optional string text = 3;
-    repeated string textlines = 700;
-    optional bool valid = 5;
-    
-    optional TestXmlChild child = 1;
-    repeated group Children = 401 
-    {
-        repeated EnumOptions options = 3;
-        optional bytes binary = 4;
-    }
-
-    extensions 100 to 199;
+  optional int64 number = 6;
+  repeated int32 numbers = 2;
+  optional string text = 3;
+  repeated string textlines = 700;
+  optional bool valid = 5;
+
+  optional TestXmlChild child = 1;
+  repeated group Children = 401 {
+    repeated EnumOptions options = 3;
+    optional bytes binary = 4;
+  }
+
+extensions 100 to 199;
 }
 
 message  TestXmlExtension {
   required int32 number = 1;
 }
-  
+
 extend TestXmlMessage {
   optional EnumOptions extension_enum = 101;
   optional string extension_text = 102;

+ 44 - 0
protos/extest/unittest_issues.proto

@@ -86,3 +86,47 @@ message NumberField {
     optional int32 _01 = 1;
 }
 
+// Issue 28: Circular message dependencies result in null defaults for DefaultInstance
+
+message MyMessageAReferenceB {
+    required MyMessageBReferenceA value = 1;
+}
+
+message MyMessageBReferenceA {
+    required MyMessageAReferenceB value = 1;
+}
+
+// issue 19 - negative enum values
+
+enum NegativeEnum {
+    FiveBelow = -5;
+    MinusOne = -1;
+    Zero = 0;
+}
+
+message NegativeEnumMessage { 
+    optional NegativeEnum value = 1;
+    repeated NegativeEnum values = 2;
+    repeated NegativeEnum packed_values = 3 [packed=true];
+}
+
+// Issue 21: http://code.google.com/p/protobuf-csharp-port/issues/detail?id=21
+// Decorate fields with [deprecated=true] as [System.Obsolete]
+
+message DeprecatedChild {
+}
+
+enum DeprecatedEnum {
+    one = 1;
+}
+
+message DeprecatedFieldsMessage {
+    optional int32 PrimitiveValue = 1 [deprecated = true];
+    repeated int32 PrimitiveArray = 2 [deprecated = true];
+
+    optional DeprecatedChild MessageValue = 3 [deprecated = true];
+    repeated DeprecatedChild MessageArray = 4 [deprecated = true];
+
+    optional DeprecatedEnum EnumValue = 5 [deprecated = true];
+    repeated DeprecatedEnum EnumArray = 6 [deprecated = true];
+}

+ 44 - 0
protos/npp.language.xml

@@ -0,0 +1,44 @@
+<NotepadPlus>
+<!--
+Defines syntax highlighting for Notepad++.
+1. Install Notepad++ from http://notepad-plus-plus.org
+2. Open Notepad++, from the View menu, select "User-Defined Dialog..."
+3. Click the "Import..." button and select this file
+4. Restart Notepad++
+5. Open and edit any *.proto file
+-->
+    <UserLang name="Proto Buffer" ext="proto">
+        <Settings>
+            <Global caseIgnored="no" />
+            <TreatAsSymbol comment="no" commentLine="yes" />
+            <Prefix words1="no" words2="no" words3="no" words4="yes" />
+        </Settings>
+        <KeywordLists>
+            <Keywords name="Delimiters">[00]00</Keywords>
+            <Keywords name="Folder+">{</Keywords>
+            <Keywords name="Folder-">}</Keywords>
+            <Keywords name="Operators">=</Keywords>
+            <Keywords name="Comment"> 1option 1package 1import 2; 0//</Keywords>
+            <Keywords name="Words1">message enum service extend</Keywords>
+            <Keywords name="Words2">required optional repeated extensions to rpc returns</Keywords>
+            <Keywords name="Words3">double float int32 int64 uint32 uint64 sint32 sint64 fixed32 fixed64 sfixed32 sfixed64 bool string bytes</Keywords>
+            <Keywords name="Words4"></Keywords>
+        </KeywordLists>
+        <Styles>
+            <WordsStyle name="DEFAULT" styleID="11" fgColor="000000" bgColor="FFFFFF" fontStyle="0" />
+            <WordsStyle name="FOLDEROPEN" styleID="12" fgColor="000000" bgColor="FFFFFF" fontStyle="1" />
+            <WordsStyle name="FOLDERCLOSE" styleID="13" fgColor="000000" bgColor="FFFFFF" fontStyle="1" />
+            <WordsStyle name="KEYWORD1" styleID="5" fgColor="0000FF" bgColor="FFFFFF" fontStyle="0" />
+            <WordsStyle name="KEYWORD2" styleID="6" fgColor="0080C0" bgColor="FFFFFF" fontStyle="0" />
+            <WordsStyle name="KEYWORD3" styleID="7" fgColor="0000FF" bgColor="FFFFFF" fontStyle="0" />
+            <WordsStyle name="KEYWORD4" styleID="8" fgColor="008040" bgColor="FFFFFF" fontStyle="0" />
+            <WordsStyle name="COMMENT" styleID="1" fgColor="008000" bgColor="FFFFFF" fontStyle="0" />
+            <WordsStyle name="COMMENT LINE" styleID="2" fgColor="949494" bgColor="FFFFFF" fontStyle="0" />
+            <WordsStyle name="NUMBER" styleID="4" fgColor="FF0000" bgColor="FFFFFF" fontStyle="0" />
+            <WordsStyle name="OPERATOR" styleID="10" fgColor="000000" bgColor="FFFFFF" fontStyle="0" />
+            <WordsStyle name="DELIMINER1" styleID="14" fgColor="800080" bgColor="FFFFFF" fontStyle="0" />
+            <WordsStyle name="DELIMINER2" styleID="15" fgColor="808080" bgColor="FFFFFF" fontStyle="0" />
+            <WordsStyle name="DELIMINER3" styleID="16" fgColor="000000" bgColor="FFFFFF" fontStyle="0" />
+        </Styles>
+    </UserLang>
+</NotepadPlus>

+ 0 - 40
readme.txt

@@ -1,40 +0,0 @@
-Welcome to the C# port of Google Protocol Buffers, written by Jon Skeet
-(skeet@pobox.com) based on the work of many talented people.
-
-For more information about this port, visit its homepage:
-http://protobuf-csharp-port.googlecode.com
-
-For more information about Protocol Buffers in general, visit the
-project page for the C++, Java and Python project:
-http://protobuf.googlecode.com
-
-
-Release 0.9.1
--------------
-
-Fix to release 0.9:
-
-- Include protos in binary download
-- Fix issue 10: incorrect encoding of packed fields when serialized
-  size wasn't fetched first
-
-
-Release 0.9
------------
-
-Due to popular demand, I have built a version of the binaries to put
-on the web site. Currently these are set at assembly version 0.9,
-and an assembly file version of 0.9. This should be seen as a mark
-of the readiness of the release process more than the stability of
-the code. As far as I'm aware, the code itself is perfectly fine: I
-certainly have plans for more features particularly around making
-code generation simpler, but you should feel confident about the
-parsing and serialization of messages produced with this version of
-the library. Of course, if you do find any problems, *please* report
-them at the web site.
-
-Currently the downloadable release is built with the snk file which
-is in the open source library. I am considering having a privately
-held key so that you can check that you're building against a
-"blessed" release - feedback on this (and any other aspect of the
-release process) is very welcome.

+ 169 - 48
src/AddressBook/AddressBookProtos.cs

@@ -1,5 +1,5 @@
 // Generated by ProtoGen, Version=2.3.0.277, Culture=neutral, PublicKeyToken=17b3b1f090c3ea48.  DO NOT EDIT!
-#pragma warning disable 1591
+#pragma warning disable 1591, 0612
 #region Designer generated code
 
 using pb = global::Google.ProtocolBuffers;
@@ -68,7 +68,8 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
   [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
   [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
   public sealed partial class Person : pb::GeneratedMessage<Person, Person.Builder> {
-    private static readonly Person defaultInstance = new Builder().BuildPartial();
+    private Person() { }
+    private static readonly Person defaultInstance = new Person().MakeReadOnly();
     private static readonly string[] _personFieldNames = new string[] { "email", "id", "name", "phone" };
     private static readonly uint[] _personFieldTags = new uint[] { 26, 16, 10, 34 };
     public static Person DefaultInstance {
@@ -76,7 +77,7 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
     }
     
     public override Person DefaultInstanceForType {
-      get { return defaultInstance; }
+      get { return DefaultInstance; }
     }
     
     protected override Person ThisMessage {
@@ -108,7 +109,8 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
       [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
       [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
       public sealed partial class PhoneNumber : pb::GeneratedMessage<PhoneNumber, PhoneNumber.Builder> {
-        private static readonly PhoneNumber defaultInstance = new Builder().BuildPartial();
+        private PhoneNumber() { }
+        private static readonly PhoneNumber defaultInstance = new PhoneNumber().MakeReadOnly();
         private static readonly string[] _phoneNumberFieldNames = new string[] { "number", "type" };
         private static readonly uint[] _phoneNumberFieldTags = new uint[] { 10, 16 };
         public static PhoneNumber DefaultInstance {
@@ -116,7 +118,7 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
         }
         
         public override PhoneNumber DefaultInstanceForType {
-          get { return defaultInstance; }
+          get { return DefaultInstance; }
         }
         
         protected override PhoneNumber ThisMessage {
@@ -219,11 +221,15 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
         public static PhoneNumber ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
           return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
         }
+        private PhoneNumber 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(PhoneNumber prototype) {
-          return (Builder) new Builder().MergeFrom(prototype);
+          return new Builder(prototype);
         }
         
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -233,21 +239,48 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
           protected override Builder ThisBuilder {
             get { return this; }
           }
-          public Builder() {}
+          public Builder() {
+            result = DefaultInstance;
+            resultIsReadOnly = true;
+          }
+          internal Builder(PhoneNumber cloneFrom) {
+            result = cloneFrom;
+            resultIsReadOnly = true;
+          }
+          
+          private bool resultIsReadOnly;
+          private PhoneNumber result;
           
-          PhoneNumber result = new PhoneNumber();
+          private PhoneNumber PrepareBuilder() {
+            if (resultIsReadOnly) {
+              PhoneNumber original = result;
+              result = new PhoneNumber();
+              resultIsReadOnly = false;
+              MergeFrom(original);
+            }
+            return result;
+          }
+          
+          public override bool IsInitialized {
+            get { return result.IsInitialized; }
+          }
           
           protected override PhoneNumber MessageBeingBuilt {
-            get { return result; }
+            get { return PrepareBuilder(); }
           }
           
           public override Builder Clear() {
-            result = new PhoneNumber();
+            result = DefaultInstance;
+            resultIsReadOnly = true;
             return this;
           }
           
           public override Builder Clone() {
-            return new Builder().MergeFrom(result);
+            if (resultIsReadOnly) {
+              return new Builder(result);
+            } else {
+              return new Builder().MergeFrom(result);
+            }
           }
           
           public override pbd::MessageDescriptor DescriptorForType {
@@ -259,12 +292,11 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
           }
           
           public override PhoneNumber BuildPartial() {
-            if (result == null) {
-              throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+            if (resultIsReadOnly) {
+              return result;
             }
-            PhoneNumber returnMe = result;
-            result = null;
-            return returnMe;
+            resultIsReadOnly = true;
+            return result.MakeReadOnly();
           }
           
           public override Builder MergeFrom(pb::IMessage other) {
@@ -278,6 +310,7 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
           
           public override Builder MergeFrom(PhoneNumber other) {
             if (other == global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber.DefaultInstance) return this;
+            PrepareBuilder();
             if (other.HasNumber) {
               Number = other.Number;
             }
@@ -293,6 +326,7 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
           }
           
           public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+            PrepareBuilder();
             pb::UnknownFieldSet.Builder unknownFields = null;
             uint tag;
             string field_name;
@@ -361,11 +395,13 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
           }
           public Builder SetNumber(string value) {
             pb::ThrowHelper.ThrowIfNull(value, "value");
+            PrepareBuilder();
             result.hasNumber = true;
             result.number_ = value;
             return this;
           }
           public Builder ClearNumber() {
+            PrepareBuilder();
             result.hasNumber = false;
             result.number_ = "";
             return this;
@@ -379,11 +415,13 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
             set { SetType(value); }
           }
           public Builder SetType(global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneType value) {
+            PrepareBuilder();
             result.hasType = true;
             result.type_ = value;
             return this;
           }
           public Builder ClearType() {
+            PrepareBuilder();
             result.hasType = false;
             result.type_ = global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneType.HOME;
             return this;
@@ -523,11 +561,16 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
     public static Person ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
       return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
     }
+    private Person MakeReadOnly() {
+      phone_.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(Person prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -537,21 +580,48 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(Person cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
       
-      Person result = new Person();
+      private bool resultIsReadOnly;
+      private Person result;
+      
+      private Person PrepareBuilder() {
+        if (resultIsReadOnly) {
+          Person original = result;
+          result = new Person();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override Person MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new Person();
+        result = DefaultInstance;
+        resultIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -563,13 +633,11 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
       }
       
       public override Person BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (resultIsReadOnly) {
+          return result;
         }
-        result.phone_.MakeReadOnly();
-        Person returnMe = result;
-        result = null;
-        return returnMe;
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -583,6 +651,7 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
       
       public override Builder MergeFrom(Person other) {
         if (other == global::Google.ProtocolBuffers.Examples.AddressBook.Person.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasName) {
           Name = other.Name;
         }
@@ -593,7 +662,7 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
           Email = other.Email;
         }
         if (other.phone_.Count != 0) {
-          base.AddRange(other.phone_, result.phone_);
+          result.phone_.Add(other.phone_);
         }
         this.MergeUnknownFields(other.UnknownFields);
         return this;
@@ -604,6 +673,7 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -672,11 +742,13 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
       }
       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;
@@ -690,11 +762,13 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
         set { SetId(value); }
       }
       public Builder SetId(int value) {
+        PrepareBuilder();
         result.hasId = true;
         result.id_ = value;
         return this;
       }
       public Builder ClearId() {
+        PrepareBuilder();
         result.hasId = false;
         result.id_ = 0;
         return this;
@@ -709,18 +783,20 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
       }
       public Builder SetEmail(string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasEmail = true;
         result.email_ = value;
         return this;
       }
       public Builder ClearEmail() {
+        PrepareBuilder();
         result.hasEmail = false;
         result.email_ = "";
         return this;
       }
       
       public pbc::IPopsicleList<global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber> PhoneList {
-        get { return result.phone_; }
+        get { return PrepareBuilder().phone_; }
       }
       public int PhoneCount {
         get { return result.PhoneCount; }
@@ -730,29 +806,35 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
       }
       public Builder SetPhone(int index, global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.phone_[index] = value;
         return this;
       }
       public Builder SetPhone(int index, global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.phone_[index] = builderForValue.Build();
         return this;
       }
       public Builder AddPhone(global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.phone_.Add(value);
         return this;
       }
       public Builder AddPhone(global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.phone_.Add(builderForValue.Build());
         return this;
       }
       public Builder AddRangePhone(scg::IEnumerable<global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber> values) {
-        base.AddRange(values, result.phone_);
+        PrepareBuilder();
+        result.phone_.Add(values);
         return this;
       }
       public Builder ClearPhone() {
+        PrepareBuilder();
         result.phone_.Clear();
         return this;
       }
@@ -766,7 +848,8 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
   [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
   [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
   public sealed partial class AddressBook : pb::GeneratedMessage<AddressBook, AddressBook.Builder> {
-    private static readonly AddressBook defaultInstance = new Builder().BuildPartial();
+    private AddressBook() { }
+    private static readonly AddressBook defaultInstance = new AddressBook().MakeReadOnly();
     private static readonly string[] _addressBookFieldNames = new string[] { "person" };
     private static readonly uint[] _addressBookFieldTags = new uint[] { 10 };
     public static AddressBook DefaultInstance {
@@ -774,7 +857,7 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
     }
     
     public override AddressBook DefaultInstanceForType {
-      get { return defaultInstance; }
+      get { return DefaultInstance; }
     }
     
     protected override AddressBook ThisMessage {
@@ -865,11 +948,16 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
     public static AddressBook ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
       return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
     }
+    private AddressBook MakeReadOnly() {
+      person_.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(AddressBook prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -879,21 +967,48 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(AddressBook cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
+      
+      private bool resultIsReadOnly;
+      private AddressBook result;
       
-      AddressBook result = new AddressBook();
+      private AddressBook PrepareBuilder() {
+        if (resultIsReadOnly) {
+          AddressBook original = result;
+          result = new AddressBook();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override AddressBook MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new AddressBook();
+        result = DefaultInstance;
+        resultIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -905,13 +1020,11 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
       }
       
       public override AddressBook BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (resultIsReadOnly) {
+          return result;
         }
-        result.person_.MakeReadOnly();
-        AddressBook returnMe = result;
-        result = null;
-        return returnMe;
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -925,8 +1038,9 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
       
       public override Builder MergeFrom(AddressBook other) {
         if (other == global::Google.ProtocolBuffers.Examples.AddressBook.AddressBook.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.person_.Count != 0) {
-          base.AddRange(other.person_, result.person_);
+          result.person_.Add(other.person_);
         }
         this.MergeUnknownFields(other.UnknownFields);
         return this;
@@ -937,6 +1051,7 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -985,7 +1100,7 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
       
       
       public pbc::IPopsicleList<global::Google.ProtocolBuffers.Examples.AddressBook.Person> PersonList {
-        get { return result.person_; }
+        get { return PrepareBuilder().person_; }
       }
       public int PersonCount {
         get { return result.PersonCount; }
@@ -995,29 +1110,35 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
       }
       public Builder SetPerson(int index, global::Google.ProtocolBuffers.Examples.AddressBook.Person value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.person_[index] = value;
         return this;
       }
       public Builder SetPerson(int index, global::Google.ProtocolBuffers.Examples.AddressBook.Person.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.person_[index] = builderForValue.Build();
         return this;
       }
       public Builder AddPerson(global::Google.ProtocolBuffers.Examples.AddressBook.Person value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.person_.Add(value);
         return this;
       }
       public Builder AddPerson(global::Google.ProtocolBuffers.Examples.AddressBook.Person.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.person_.Add(builderForValue.Build());
         return this;
       }
       public Builder AddRangePerson(scg::IEnumerable<global::Google.ProtocolBuffers.Examples.AddressBook.Person> values) {
-        base.AddRange(values, result.person_);
+        PrepareBuilder();
+        result.person_.Add(values);
         return this;
       }
       public Builder ClearPerson() {
+        PrepareBuilder();
         result.person_.Clear();
         return this;
       }

+ 6 - 6
src/ProtoGen.Test/DependencyResolutionTest.cs

@@ -52,7 +52,7 @@ namespace Google.ProtocolBuffers.ProtoGen
         {
             FileDescriptorProto first = new FileDescriptorProto.Builder {Name = "First"}.Build();
             FileDescriptorProto second = new FileDescriptorProto.Builder {Name = "Second"}.Build();
-            FileDescriptorSet set = new FileDescriptorSet {FileList = {first, second}};
+            FileDescriptorSet set = new FileDescriptorSet.Builder { FileList = { first, second } }.Build();
 
             IList<FileDescriptor> converted = Generator.ConvertDescriptors(CSharpFileOptions.DefaultInstance, set);
             Assert.AreEqual(2, converted.Count);
@@ -68,7 +68,7 @@ namespace Google.ProtocolBuffers.ProtoGen
             FileDescriptorProto first =
                 new FileDescriptorProto.Builder {Name = "First", DependencyList = {"Second"}}.Build();
             FileDescriptorProto second = new FileDescriptorProto.Builder {Name = "Second"}.Build();
-            FileDescriptorSet set = new FileDescriptorSet {FileList = {first, second}};
+            FileDescriptorSet set = new FileDescriptorSet.Builder { FileList = { first, second } }.Build();
             IList<FileDescriptor> converted = Generator.ConvertDescriptors(CSharpFileOptions.DefaultInstance, set);
             Assert.AreEqual(2, converted.Count);
             Assert.AreEqual("First", converted[0].Name);
@@ -84,7 +84,7 @@ namespace Google.ProtocolBuffers.ProtoGen
             FileDescriptorProto first = new FileDescriptorProto.Builder {Name = "First"}.Build();
             FileDescriptorProto second =
                 new FileDescriptorProto.Builder {Name = "Second", DependencyList = {"First"}}.Build();
-            FileDescriptorSet set = new FileDescriptorSet {FileList = {first, second}};
+            FileDescriptorSet set = new FileDescriptorSet.Builder { FileList = { first, second } }.Build();
             IList<FileDescriptor> converted = Generator.ConvertDescriptors(CSharpFileOptions.DefaultInstance, set);
             Assert.AreEqual(2, converted.Count);
             Assert.AreEqual("First", converted[0].Name);
@@ -101,7 +101,7 @@ namespace Google.ProtocolBuffers.ProtoGen
                 new FileDescriptorProto.Builder {Name = "First", DependencyList = {"Second"}}.Build();
             FileDescriptorProto second =
                 new FileDescriptorProto.Builder {Name = "Second", DependencyList = {"First"}}.Build();
-            FileDescriptorSet set = new FileDescriptorSet {FileList = {first, second}};
+            FileDescriptorSet set = new FileDescriptorSet.Builder { FileList = { first, second } }.Build();
             try
             {
                 Generator.ConvertDescriptors(CSharpFileOptions.DefaultInstance, set);
@@ -118,7 +118,7 @@ namespace Google.ProtocolBuffers.ProtoGen
         {
             FileDescriptorProto first =
                 new FileDescriptorProto.Builder {Name = "First", DependencyList = {"Second"}}.Build();
-            FileDescriptorSet set = new FileDescriptorSet {FileList = {first}};
+            FileDescriptorSet set = new FileDescriptorSet.Builder { FileList = { first } }.Build();
             try
             {
                 Generator.ConvertDescriptors(CSharpFileOptions.DefaultInstance, set);
@@ -135,7 +135,7 @@ namespace Google.ProtocolBuffers.ProtoGen
         {
             FileDescriptorProto first =
                 new FileDescriptorProto.Builder {Name = "First", DependencyList = {"First"}}.Build();
-            FileDescriptorSet set = new FileDescriptorSet {FileList = {first}};
+            FileDescriptorSet set = new FileDescriptorSet.Builder { FileList = { first } }.Build();
             try
             {
                 Generator.ConvertDescriptors(CSharpFileOptions.DefaultInstance, set);

+ 8 - 3
src/ProtoGen/EnumFieldGenerator.cs

@@ -49,10 +49,11 @@ namespace Google.ProtocolBuffers.ProtoGen
         {
             writer.WriteLine("private bool has{0};", PropertyName);
             writer.WriteLine("private {0} {1}_ = {2};", TypeName, Name, DefaultValue);
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public bool Has{0} {{", PropertyName);
             writer.WriteLine("  get {{ return has{0}; }}", PropertyName);
             writer.WriteLine("}");
-            AddClsComplianceCheck(writer);
+            AddPublicMemberAttributes(writer);
             writer.WriteLine("public {0} {1} {{", TypeName, PropertyName);
             writer.WriteLine("  get {{ return {0}_; }}", Name);
             writer.WriteLine("}");
@@ -60,21 +61,25 @@ namespace Google.ProtocolBuffers.ProtoGen
 
         public void GenerateBuilderMembers(TextGenerator writer)
         {
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public bool Has{0} {{", PropertyName);
             writer.WriteLine(" get {{ return result.has{0}; }}", PropertyName);
             writer.WriteLine("}");
-            AddClsComplianceCheck(writer);
+            AddPublicMemberAttributes(writer);
             writer.WriteLine("public {0} {1} {{", TypeName, PropertyName);
             writer.WriteLine("  get {{ return result.{0}; }}", PropertyName);
             writer.WriteLine("  set {{ Set{0}(value); }}", PropertyName);
             writer.WriteLine("}");
-            AddClsComplianceCheck(writer);
+            AddPublicMemberAttributes(writer);
             writer.WriteLine("public Builder Set{0}({1} value) {{", PropertyName, TypeName);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.has{0} = true;", PropertyName);
             writer.WriteLine("  result.{0}_ = value;", Name);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public Builder Clear{0}() {{", PropertyName);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.has{0} = false;", PropertyName);
             writer.WriteLine("  result.{0}_ = {1};", Name, DefaultValue);
             writer.WriteLine("  return this;");

+ 19 - 0
src/ProtoGen/FieldGeneratorBase.cs

@@ -251,6 +251,12 @@ namespace Google.ProtocolBuffers.ProtoGen
             }
         }
 
+        protected void AddPublicMemberAttributes(TextGenerator writer)
+        {
+            AddDeprecatedFlag(writer);
+            AddClsComplianceCheck(writer);
+        }
+
         protected void AddClsComplianceCheck(TextGenerator writer)
         {
             if (!Descriptor.IsCLSCompliant && Descriptor.File.CSharpOptions.ClsCompliance)
@@ -259,6 +265,19 @@ namespace Google.ProtocolBuffers.ProtoGen
             }
         }
 
+        protected bool IsObsolete { get { return Descriptor.Options.Deprecated; } }
+
+        /// <summary>
+        /// Writes [global::System.ObsoleteAttribute()] if the member is obsolete
+        /// </summary>
+        protected void AddDeprecatedFlag(TextGenerator writer)
+        {
+            if (IsObsolete)
+            {
+                writer.WriteLine("[global::System.ObsoleteAttribute()]");
+            }
+        }
+
         /// <summary>
         /// For encodings with fixed sizes, returns that size in bytes.  Otherwise
         /// returns -1. TODO(jonskeet): Make this less ugly.

+ 15 - 3
src/ProtoGen/MessageFieldGenerator.cs

@@ -48,38 +48,48 @@ namespace Google.ProtocolBuffers.ProtoGen
         public void GenerateMembers(TextGenerator writer)
         {
             writer.WriteLine("private bool has{0};", PropertyName);
-            writer.WriteLine("private {0} {1}_ = {2};", TypeName, Name, DefaultValue);
+            writer.WriteLine("private {0} {1}_;", TypeName, Name);
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public bool Has{0} {{", PropertyName);
             writer.WriteLine("  get {{ return has{0}; }}", PropertyName);
             writer.WriteLine("}");
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public {0} {1} {{", TypeName, PropertyName);
-            writer.WriteLine("  get {{ return {0}_; }}", Name);
+            writer.WriteLine("  get {{ return {0}_ ?? {1}; }}", Name, DefaultValue);
             writer.WriteLine("}");
         }
 
         public void GenerateBuilderMembers(TextGenerator writer)
         {
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public bool Has{0} {{", PropertyName);
             writer.WriteLine(" get {{ return result.has{0}; }}", PropertyName);
             writer.WriteLine("}");
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public {0} {1} {{", TypeName, PropertyName);
             writer.WriteLine("  get {{ return result.{0}; }}", PropertyName);
             writer.WriteLine("  set {{ Set{0}(value); }}", PropertyName);
             writer.WriteLine("}");
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public Builder Set{0}({1} value) {{", PropertyName, TypeName);
             AddNullCheck(writer);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.has{0} = true;", PropertyName);
             writer.WriteLine("  result.{0}_ = value;", Name);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public Builder Set{0}({1}.Builder builderForValue) {{", PropertyName, TypeName);
             AddNullCheck(writer, "builderForValue");
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.has{0} = true;", PropertyName);
             writer.WriteLine("  result.{0}_ = builderForValue.Build();", Name);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public Builder Merge{0}({1} value) {{", PropertyName, TypeName);
             AddNullCheck(writer);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  if (result.has{0} &&", PropertyName);
             writer.WriteLine("      result.{0}_ != {1}) {{", Name, DefaultValue);
             writer.WriteLine("      result.{0}_ = {1}.CreateBuilder(result.{0}_).MergeFrom(value).BuildPartial();", Name,
@@ -90,9 +100,11 @@ namespace Google.ProtocolBuffers.ProtoGen
             writer.WriteLine("  result.has{0} = true;", PropertyName);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public Builder Clear{0}() {{", PropertyName);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.has{0} = false;", PropertyName);
-            writer.WriteLine("  result.{0}_ = {1};", Name, DefaultValue);
+            writer.WriteLine("  result.{0}_ = null;", Name);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
         }

+ 57 - 18
src/ProtoGen/MessageGenerator.cs

@@ -181,8 +181,9 @@ namespace Google.ProtocolBuffers.ProtoGen
                              Descriptor.Proto.ExtensionRangeCount > 0 ? "Extendable" : "Generated",
                              RuntimeSuffix);
             writer.Indent();
+            writer.WriteLine("private {0}() {{ }}", ClassName);
             // Must call BuildPartial() to make sure all lists are made read-only
-            writer.WriteLine("private static readonly {0} defaultInstance = new Builder().BuildPartial();", ClassName);
+            writer.WriteLine("private static readonly {0} defaultInstance = new {0}().MakeReadOnly();", ClassName);
 
             if (OptimizeSpeed)
             {
@@ -203,7 +204,7 @@ namespace Google.ProtocolBuffers.ProtoGen
             writer.WriteLine("}");
             writer.WriteLine();
             writer.WriteLine("public override {0} DefaultInstanceForType {{", ClassName);
-            writer.WriteLine("  get { return defaultInstance; }");
+            writer.WriteLine("  get { return DefaultInstance; }");
             writer.WriteLine("}");
             writer.WriteLine();
             writer.WriteLine("protected override {0} ThisMessage {{", ClassName);
@@ -551,11 +552,22 @@ namespace Google.ProtocolBuffers.ProtoGen
 
         private void GenerateBuilder(TextGenerator writer)
         {
+            writer.WriteLine("private {0} MakeReadOnly() {{", ClassName);
+            writer.Indent();
+            foreach (FieldDescriptor field in Descriptor.Fields)
+            {
+                CreateFieldGenerator(field).GenerateBuildingCode(writer);
+            }
+            writer.WriteLine("return this;");
+            writer.Outdent();
+            writer.WriteLine("}");
+            writer.WriteLine();
+
             writer.WriteLine("public static Builder CreateBuilder() { return new Builder(); }");
             writer.WriteLine("public override Builder ToBuilder() { return CreateBuilder(this); }");
             writer.WriteLine("public override Builder CreateBuilderForType() { return new Builder(); }");
             writer.WriteLine("public static Builder CreateBuilder({0} prototype) {{", ClassName);
-            writer.WriteLine("  return (Builder) new Builder().MergeFrom(prototype);");
+            writer.WriteLine("  return new Builder(prototype);");
             writer.WriteLine("}");
             writer.WriteLine();
             if (Descriptor.File.CSharpOptions.AddSerializable)
@@ -590,21 +602,52 @@ namespace Google.ProtocolBuffers.ProtoGen
 
         private void GenerateCommonBuilderMethods(TextGenerator writer)
         {
-            writer.WriteLine("public Builder() {{}}", ClassAccessLevel);
+            //default constructor
+            writer.WriteLine("public Builder() {");
+            //Durring static initialization of message, DefaultInstance is expected to return null.
+            writer.WriteLine("  result = DefaultInstance;");
+            writer.WriteLine("  resultIsReadOnly = true;");
+            writer.WriteLine("}");
+            //clone constructor
+            writer.WriteLine("internal Builder({0} cloneFrom) {{", ClassName);
+            writer.WriteLine("  result = cloneFrom;");
+            writer.WriteLine("  resultIsReadOnly = true;");
+            writer.WriteLine("}");
             writer.WriteLine();
-            writer.WriteLine("{0} result = new {0}();", ClassName);
+            writer.WriteLine("private bool resultIsReadOnly;");
+            writer.WriteLine("private {0} result;", ClassName);
+            writer.WriteLine();
+            writer.WriteLine("private {0} PrepareBuilder() {{", ClassName);
+            writer.WriteLine("  if (resultIsReadOnly) {");
+            writer.WriteLine("    {0} original = result;", ClassName);
+            writer.WriteLine("    result = new {0}();", ClassName);
+            writer.WriteLine("    resultIsReadOnly = false;");
+            writer.WriteLine("    MergeFrom(original);");
+            writer.WriteLine("  }");
+            writer.WriteLine("  return result;");
+            writer.WriteLine("}");
+            writer.WriteLine();
+            writer.WriteLine("public override bool IsInitialized {");
+            writer.WriteLine("  get { return result.IsInitialized; }");
+            writer.WriteLine("}");
             writer.WriteLine();
             writer.WriteLine("protected override {0} MessageBeingBuilt {{", ClassName);
-            writer.WriteLine("  get { return result; }");
+            writer.WriteLine("  get { return PrepareBuilder(); }");
             writer.WriteLine("}");
             writer.WriteLine();
+            //Not actually expecting that DefaultInstance would ever be null here; however, we will ensure it does not break
             writer.WriteLine("public override Builder Clear() {");
-            writer.WriteLine("  result = new {0}();", ClassName);
+            writer.WriteLine("  result = DefaultInstance;", ClassName);
+            writer.WriteLine("  resultIsReadOnly = true;");
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
             writer.WriteLine();
             writer.WriteLine("public override Builder Clone() {");
-            writer.WriteLine("  return new Builder().MergeFrom(result);");
+            writer.WriteLine("  if (resultIsReadOnly) {");
+            writer.WriteLine("    return new Builder(result);");
+            writer.WriteLine("  } else {");
+            writer.WriteLine("    return new Builder().MergeFrom(result);");
+            writer.WriteLine("  }");
             writer.WriteLine("}");
             writer.WriteLine();
             if (!UseLiteRuntime)
@@ -621,17 +664,11 @@ namespace Google.ProtocolBuffers.ProtoGen
 
             writer.WriteLine("public override {0} BuildPartial() {{", ClassName);
             writer.Indent();
-            writer.WriteLine("if (result == null) {");
-            writer.WriteLine(
-                "  throw new global::System.InvalidOperationException(\"build() has already been called on this Builder\");");
+            writer.WriteLine("if (resultIsReadOnly) {");
+            writer.WriteLine("  return result;");
             writer.WriteLine("}");
-            foreach (FieldDescriptor field in Descriptor.Fields)
-            {
-                CreateFieldGenerator(field).GenerateBuildingCode(writer);
-            }
-            writer.WriteLine("{0} returnMe = result;", ClassName);
-            writer.WriteLine("result = null;");
-            writer.WriteLine("return returnMe;");
+            writer.WriteLine("resultIsReadOnly = true;");
+            writer.WriteLine("return result.MakeReadOnly();");
             writer.Outdent();
             writer.WriteLine("}");
             writer.WriteLine();
@@ -652,6 +689,7 @@ namespace Google.ProtocolBuffers.ProtoGen
                 // fields are set so we can skip the merge.
                 writer.Indent();
                 writer.WriteLine("if (other == {0}.DefaultInstance) return this;", FullClassName);
+                writer.WriteLine("PrepareBuilder();");
                 foreach (FieldDescriptor field in Descriptor.Fields)
                 {
                     CreateFieldGenerator(field).GenerateMergingCode(writer);
@@ -684,6 +722,7 @@ namespace Google.ProtocolBuffers.ProtoGen
             writer.WriteLine(
                 "public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {");
             writer.Indent();
+            writer.WriteLine("PrepareBuilder();");
             if (!UseLiteRuntime)
             {
                 writer.WriteLine("pb::UnknownFieldSet.Builder unknownFields = null;");

+ 8 - 3
src/ProtoGen/PrimitiveFieldGenerator.cs

@@ -50,10 +50,11 @@ namespace Google.ProtocolBuffers.ProtoGen
         {
             writer.WriteLine("private bool has{0};", PropertyName);
             writer.WriteLine("private {0} {1}_{2};", TypeName, Name, HasDefaultValue ? " = " + DefaultValue : "");
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public bool Has{0} {{", PropertyName);
             writer.WriteLine("  get {{ return has{0}; }}", PropertyName);
             writer.WriteLine("}");
-            AddClsComplianceCheck(writer);
+            AddPublicMemberAttributes(writer);
             writer.WriteLine("public {0} {1} {{", TypeName, PropertyName);
             writer.WriteLine("  get {{ return {0}_; }}", Name);
             writer.WriteLine("}");
@@ -61,22 +62,26 @@ namespace Google.ProtocolBuffers.ProtoGen
 
         public void GenerateBuilderMembers(TextGenerator writer)
         {
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public bool Has{0} {{", PropertyName);
             writer.WriteLine("  get {{ return result.has{0}; }}", PropertyName);
             writer.WriteLine("}");
-            AddClsComplianceCheck(writer);
+            AddPublicMemberAttributes(writer);
             writer.WriteLine("public {0} {1} {{", TypeName, PropertyName);
             writer.WriteLine("  get {{ return result.{0}; }}", PropertyName);
             writer.WriteLine("  set {{ Set{0}(value); }}", PropertyName);
             writer.WriteLine("}");
-            AddClsComplianceCheck(writer);
+            AddPublicMemberAttributes(writer);
             writer.WriteLine("public Builder Set{0}({1} value) {{", PropertyName, TypeName);
             AddNullCheck(writer);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.has{0} = true;", PropertyName);
             writer.WriteLine("  result.{0}_ = value;", Name);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public Builder Clear{0}() {{", PropertyName);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.has{0} = false;", PropertyName);
             writer.WriteLine("  result.{0}_ = {1};", Name, DefaultValue);
             writer.WriteLine("  return this;");

+ 18 - 4
src/ProtoGen/RepeatedEnumFieldGenerator.cs

@@ -52,15 +52,18 @@ namespace Google.ProtocolBuffers.ProtoGen
                 writer.WriteLine("private int {0}MemoizedSerializedSize;", Name);
             }
             writer.WriteLine("private pbc::PopsicleList<{0}> {1}_ = new pbc::PopsicleList<{0}>();", TypeName, Name);
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public scg::IList<{0}> {1}List {{", TypeName, PropertyName);
             writer.WriteLine("  get {{ return pbc::Lists.AsReadOnly({0}_); }}", Name);
             writer.WriteLine("}");
 
             // TODO(jonskeet): Redundant API calls? Possibly - include for portability though. Maybe create an option.
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public int {0}Count {{", PropertyName);
             writer.WriteLine("  get {{ return {0}_.Count; }}", Name);
             writer.WriteLine("}");
 
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public {0} Get{1}(int index) {{", TypeName, PropertyName);
             writer.WriteLine("  return {0}_[index];", Name);
             writer.WriteLine("}");
@@ -70,28 +73,39 @@ namespace Google.ProtocolBuffers.ProtoGen
         {
             // Note:  We can return the original list here, because we make it unmodifiable when we build
             // We return it via IPopsicleList so that collection initializers work more pleasantly.
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public pbc::IPopsicleList<{0}> {1}List {{", TypeName, PropertyName);
-            writer.WriteLine("  get {{ return result.{0}_; }}", Name);
+            writer.WriteLine("  get {{ return PrepareBuilder().{0}_; }}", Name);
             writer.WriteLine("}");
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public int {0}Count {{", PropertyName);
             writer.WriteLine("  get {{ return result.{0}Count; }}", PropertyName);
             writer.WriteLine("}");
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public {0} Get{1}(int index) {{", TypeName, PropertyName);
             writer.WriteLine("  return result.Get{0}(index);", PropertyName);
             writer.WriteLine("}");
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public Builder Set{0}(int index, {1} value) {{", PropertyName, TypeName);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.{0}_[index] = value;", Name);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public Builder Add{0}({1} value) {{", PropertyName, TypeName);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.{0}_.Add(value);", Name, TypeName);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public Builder AddRange{0}(scg::IEnumerable<{1}> values) {{", PropertyName, TypeName);
-            writer.WriteLine("  base.AddRange(values, result.{0}_);", Name);
+            writer.WriteLine("  PrepareBuilder();");
+            writer.WriteLine("  result.{0}_.Add(values);", Name);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public Builder Clear{0}() {{", PropertyName);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.{0}_.Clear();", Name);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
@@ -100,13 +114,13 @@ namespace Google.ProtocolBuffers.ProtoGen
         public void GenerateMergingCode(TextGenerator writer)
         {
             writer.WriteLine("if (other.{0}_.Count != 0) {{", Name);
-            writer.WriteLine("  base.AddRange(other.{0}_, result.{0}_);", Name);
+            writer.WriteLine("  result.{0}_.Add(other.{0}_);", Name);
             writer.WriteLine("}");
         }
 
         public void GenerateBuildingCode(TextGenerator writer)
         {
-            writer.WriteLine("result.{0}_.MakeReadOnly();", Name);
+            writer.WriteLine("{0}_.MakeReadOnly();", Name);
         }
 
         public void GenerateParsingCode(TextGenerator writer)

+ 22 - 4
src/ProtoGen/RepeatedMessageFieldGenerator.cs

@@ -48,15 +48,18 @@ namespace Google.ProtocolBuffers.ProtoGen
         public void GenerateMembers(TextGenerator writer)
         {
             writer.WriteLine("private pbc::PopsicleList<{0}> {1}_ = new pbc::PopsicleList<{0}>();", TypeName, Name);
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public scg::IList<{0}> {1}List {{", TypeName, PropertyName);
             writer.WriteLine("  get {{ return {0}_; }}", Name);
             writer.WriteLine("}");
 
             // TODO(jonskeet): Redundant API calls? Possibly - include for portability though. Maybe create an option.
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public int {0}Count {{", PropertyName);
             writer.WriteLine("  get {{ return {0}_.Count; }}", Name);
             writer.WriteLine("}");
 
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public {0} Get{1}(int index) {{", TypeName, PropertyName);
             writer.WriteLine("  return {0}_[index];", Name);
             writer.WriteLine("}");
@@ -66,42 +69,57 @@ namespace Google.ProtocolBuffers.ProtoGen
         {
             // Note:  We can return the original list here, because we make it unmodifiable when we build
             // We return it via IPopsicleList so that collection initializers work more pleasantly.
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public pbc::IPopsicleList<{0}> {1}List {{", TypeName, PropertyName);
-            writer.WriteLine("  get {{ return result.{0}_; }}", Name);
+            writer.WriteLine("  get {{ return PrepareBuilder().{0}_; }}", Name);
             writer.WriteLine("}");
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public int {0}Count {{", PropertyName);
             writer.WriteLine("  get {{ return result.{0}Count; }}", PropertyName);
             writer.WriteLine("}");
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public {0} Get{1}(int index) {{", TypeName, PropertyName);
             writer.WriteLine("  return result.Get{0}(index);", PropertyName);
             writer.WriteLine("}");
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public Builder Set{0}(int index, {1} value) {{", PropertyName, TypeName);
             AddNullCheck(writer);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.{0}_[index] = value;", Name);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
             // Extra overload for builder (just on messages)
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public Builder Set{0}(int index, {1}.Builder builderForValue) {{", PropertyName, TypeName);
             AddNullCheck(writer, "builderForValue");
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.{0}_[index] = builderForValue.Build();", Name);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public Builder Add{0}({1} value) {{", PropertyName, TypeName);
             AddNullCheck(writer);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.{0}_.Add(value);", Name, TypeName);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
             // Extra overload for builder (just on messages)
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public Builder Add{0}({1}.Builder builderForValue) {{", PropertyName, TypeName);
             AddNullCheck(writer, "builderForValue");
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.{0}_.Add(builderForValue.Build());", Name);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public Builder AddRange{0}(scg::IEnumerable<{1}> values) {{", PropertyName, TypeName);
-            writer.WriteLine("  base.AddRange(values, result.{0}_);", Name);
+            writer.WriteLine("  PrepareBuilder();");
+            writer.WriteLine("  result.{0}_.Add(values);", Name);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public Builder Clear{0}() {{", PropertyName);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.{0}_.Clear();", Name);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
@@ -110,13 +128,13 @@ namespace Google.ProtocolBuffers.ProtoGen
         public void GenerateMergingCode(TextGenerator writer)
         {
             writer.WriteLine("if (other.{0}_.Count != 0) {{", Name);
-            writer.WriteLine("  base.AddRange(other.{0}_, result.{0}_);", Name);
+            writer.WriteLine("  result.{0}_.Add(other.{0}_);", Name);
             writer.WriteLine("}");
         }
 
         public void GenerateBuildingCode(TextGenerator writer)
         {
-            writer.WriteLine("result.{0}_.MakeReadOnly();", Name);
+            writer.WriteLine("{0}_.MakeReadOnly();", Name);
         }
 
         public void GenerateParsingCode(TextGenerator writer)

+ 18 - 11
src/ProtoGen/RepeatedPrimitiveFieldGenerator.cs

@@ -52,17 +52,18 @@ namespace Google.ProtocolBuffers.ProtoGen
                 writer.WriteLine("private int {0}MemoizedSerializedSize;", Name);
             }
             writer.WriteLine("private pbc::PopsicleList<{0}> {1}_ = new pbc::PopsicleList<{0}>();", TypeName, Name);
-            AddClsComplianceCheck(writer);
+            AddPublicMemberAttributes(writer);
             writer.WriteLine("public scg::IList<{0}> {1}List {{", TypeName, PropertyName);
             writer.WriteLine("  get {{ return pbc::Lists.AsReadOnly({0}_); }}", Name);
             writer.WriteLine("}");
 
             // TODO(jonskeet): Redundant API calls? Possibly - include for portability though. Maybe create an option.
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public int {0}Count {{", PropertyName);
             writer.WriteLine("  get {{ return {0}_.Count; }}", Name);
             writer.WriteLine("}");
 
-            AddClsComplianceCheck(writer);
+            AddPublicMemberAttributes(writer);
             writer.WriteLine("public {0} Get{1}(int index) {{", TypeName, PropertyName);
             writer.WriteLine("  return {0}_[index];", Name);
             writer.WriteLine("}");
@@ -72,35 +73,41 @@ namespace Google.ProtocolBuffers.ProtoGen
         {
             // Note:  We can return the original list here, because we make it unmodifiable when we build
             // We return it via IPopsicleList so that collection initializers work more pleasantly.
-            AddClsComplianceCheck(writer);
+            AddPublicMemberAttributes(writer);
             writer.WriteLine("public pbc::IPopsicleList<{0}> {1}List {{", TypeName, PropertyName);
-            writer.WriteLine("  get {{ return result.{0}_; }}", Name);
+            writer.WriteLine("  get {{ return PrepareBuilder().{0}_; }}", Name);
             writer.WriteLine("}");
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public int {0}Count {{", PropertyName);
             writer.WriteLine("  get {{ return result.{0}Count; }}", PropertyName);
             writer.WriteLine("}");
-            AddClsComplianceCheck(writer);
+            AddPublicMemberAttributes(writer);
             writer.WriteLine("public {0} Get{1}(int index) {{", TypeName, PropertyName);
             writer.WriteLine("  return result.Get{0}(index);", PropertyName);
             writer.WriteLine("}");
-            AddClsComplianceCheck(writer);
+            AddPublicMemberAttributes(writer);
             writer.WriteLine("public Builder Set{0}(int index, {1} value) {{", PropertyName, TypeName);
             AddNullCheck(writer);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.{0}_[index] = value;", Name);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
-            AddClsComplianceCheck(writer);
+            AddPublicMemberAttributes(writer);
             writer.WriteLine("public Builder Add{0}({1} value) {{", PropertyName, TypeName);
             AddNullCheck(writer);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.{0}_.Add(value);", Name, TypeName);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
-            AddClsComplianceCheck(writer);
+            AddPublicMemberAttributes(writer);
             writer.WriteLine("public Builder AddRange{0}(scg::IEnumerable<{1}> values) {{", PropertyName, TypeName);
-            writer.WriteLine("  base.AddRange(values, result.{0}_);", Name);
+            writer.WriteLine("  PrepareBuilder();");
+            writer.WriteLine("  result.{0}_.Add(values);", Name);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
+            AddDeprecatedFlag(writer);
             writer.WriteLine("public Builder Clear{0}() {{", PropertyName);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.{0}_.Clear();", Name);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
@@ -109,13 +116,13 @@ namespace Google.ProtocolBuffers.ProtoGen
         public void GenerateMergingCode(TextGenerator writer)
         {
             writer.WriteLine("if (other.{0}_.Count != 0) {{", Name);
-            writer.WriteLine("  base.AddRange(other.{0}_, result.{0}_);", Name);
+            writer.WriteLine("  result.{0}_.Add(other.{0}_);", Name);
             writer.WriteLine("}");
         }
 
         public void GenerateBuildingCode(TextGenerator writer)
         {
-            writer.WriteLine("result.{0}_.MakeReadOnly();", Name);
+            writer.WriteLine("{0}_.MakeReadOnly();", Name);
         }
 
         public void GenerateParsingCode(TextGenerator writer)

+ 2 - 2
src/ProtoGen/UmbrellaClassGenerator.cs

@@ -138,8 +138,8 @@ namespace Google.ProtocolBuffers.ProtoGen
 
         private void WriteIntroduction(TextGenerator writer)
         {
-            writer.WriteLine("// Generated by {0}.  DO NOT EDIT!", this.GetType().Assembly.FullName);
-            writer.WriteLine("#pragma warning disable 1591");
+            writer.WriteLine("// Generated by {0}.  DO NOT EDIT!", this.GetType().Assembly.FullName);
+            writer.WriteLine("#pragma warning disable 1591, 0612");
             writer.WriteLine("#region Designer generated code");
 
             writer.WriteLine();

+ 10 - 6
src/ProtocolBuffers.Serialization/AbstractReader.cs

@@ -17,12 +17,6 @@ namespace Google.ProtocolBuffers.Serialization
         
         /// <summary> Constructs a new reader </summary>
         protected AbstractReader() { MaxDepth = DefaultMaxDepth; }
-        /// <summary> Constructs a new child reader </summary>
-        protected AbstractReader(AbstractReader copyFrom)
-        {
-            _depth = copyFrom._depth + 1;
-            MaxDepth = copyFrom.MaxDepth;
-        }
 
         /// <summary> Gets or sets the maximum recursion depth allowed </summary>
         public int MaxDepth { get; set; }
@@ -112,6 +106,16 @@ namespace Google.ProtocolBuffers.Serialization
         /// Merges the input stream into the provided IBuilderLite 
         /// </summary>
         protected abstract bool ReadMessage(IBuilderLite builder, ExtensionRegistry registry);
+        
+        /// <summary>
+        /// Reads the root-message preamble specific to this formatter
+        /// </summary>
+        public abstract void ReadMessageStart();
+
+        /// <summary>
+        /// Reads the root-message close specific to this formatter
+        /// </summary>
+        public abstract void ReadMessageEnd();
 
         /// <summary>
         /// Merges the input stream into the provided IBuilderLite 

+ 0 - 4
src/ProtocolBuffers.Serialization/AbstractTextReader.cs

@@ -11,10 +11,6 @@ namespace Google.ProtocolBuffers.Serialization
     {
         /// <summary> Constructs a new reader </summary>
         protected AbstractTextReader() { }
-        /// <summary> Constructs a new child reader </summary>
-        protected AbstractTextReader(AbstractTextReader copyFrom)
-            : base(copyFrom)
-        { }
 
         /// <summary>
         /// Reads a typed field as a string

+ 19 - 16
src/ProtocolBuffers.Serialization/AbstractWriter.cs

@@ -12,36 +12,39 @@ namespace Google.ProtocolBuffers.Serialization
     /// <summary>
     /// Provides a base class for writers that performs some basic type dispatching
     /// </summary>
-    public abstract class AbstractWriter : ICodedOutputStream, IDisposable
+    public abstract class AbstractWriter : ICodedOutputStream
     {
         /// <summary>
-        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+        /// Completes any pending write operations
         /// </summary>
-        public void Dispose()
+        public virtual void Flush()
         {
-            GC.SuppressFinalize(this);
-            Flush();
-            Dispose(true);
         }
 
         /// <summary>
-        /// Completes any pending write operations
+        /// Writes the message to the the formatted stream.
         /// </summary>
-        public virtual void Flush()
-        {
-        }
+        public abstract void WriteMessage(IMessageLite message);
 
         /// <summary>
-        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+        /// Used to write any nessary root-message preamble. After this call you can call 
+        /// IMessageLite.MergeTo(...) and complete the message with a call to WriteMessageEnd().
+        /// These three calls are identical to just calling WriteMessage(message);
         /// </summary>
-        protected virtual void Dispose(bool disposing)
-        {
-        }
+        /// <example>
+        /// AbstractWriter writer;
+        /// writer.WriteMessageStart();
+        /// message.WriteTo(writer);
+        /// writer.WriteMessageEnd();
+        /// // ... or, but not both ...
+        /// writer.WriteMessage(message);
+        /// </example>
+        public abstract void WriteMessageStart();
 
         /// <summary>
-        /// Writes the message to the the formatted stream.
+        /// Used to complete a root-message previously started with a call to WriteMessageStart()
         /// </summary>
-        public abstract void WriteMessage(IMessageLite message);
+        public abstract void WriteMessageEnd();
 
         /// <summary>
         /// Writes a Boolean value

+ 13 - 1
src/ProtocolBuffers.Serialization/DictionaryReader.cs

@@ -1,4 +1,4 @@
-using System;
+using System;
 using System.Collections.Generic;
 using System.Globalization;
 using Google.ProtocolBuffers.Descriptors;
@@ -22,6 +22,18 @@ namespace Google.ProtocolBuffers.Serialization
             _ready = _input.MoveNext();
         }
 
+        /// <summary>
+        /// No-op
+        /// </summary>
+        public override void ReadMessageStart()
+        { }
+
+        /// <summary>
+        /// No-op
+        /// </summary>
+        public override void ReadMessageEnd()
+        { }
+
         /// <summary>
         /// Merges the contents of stream into the provided message builder
         /// </summary>

+ 14 - 1
src/ProtocolBuffers.Serialization/DictionaryWriter.cs

@@ -1,4 +1,4 @@
-using System;
+using System;
 using System.Collections;
 using System.Collections.Generic;
 using Google.ProtocolBuffers.Descriptors;
@@ -53,6 +53,19 @@ namespace Google.ProtocolBuffers.Serialization
             message.WriteTo(this);
         }
 
+
+        /// <summary>
+        /// No-op
+        /// </summary>
+        public override void WriteMessageStart()
+        { }
+
+        /// <summary>
+        /// No-op
+        /// </summary>
+        public override void WriteMessageEnd()
+        { }
+
         /// <summary>
         /// Writes a Boolean value
         /// </summary>

+ 162 - 0
src/ProtocolBuffers.Serialization/Http/FormUrlEncodedReader.cs

@@ -0,0 +1,162 @@
+using System;
+using System.IO;
+using System.Text;
+
+namespace Google.ProtocolBuffers.Serialization.Http
+{
+    /// <summary>
+    /// Allows reading messages from a name/value dictionary
+    /// </summary>
+    public class FormUrlEncodedReader : AbstractTextReader
+    {
+        private readonly TextReader _input;
+        private string _fieldName, _fieldValue;
+        private bool _ready;
+
+        /// <summary>
+        /// Creates a dictionary reader from an enumeration of KeyValuePair data, like an IDictionary
+        /// </summary>
+        FormUrlEncodedReader(TextReader input)
+        {
+            _input = input;
+            int ch = input.Peek();
+            if (ch == '?')
+            {
+                input.Read();
+            }
+            _ready = ReadNext();
+        }
+
+        #region CreateInstance overloads
+        /// <summary>
+        /// Constructs a FormUrlEncodedReader to parse form data, or url query text into a message.
+        /// </summary>
+        public static FormUrlEncodedReader CreateInstance(Stream stream)
+        {
+            return new FormUrlEncodedReader(new StreamReader(stream, Encoding.UTF8, false));
+        }
+
+        /// <summary>
+        /// Constructs a FormUrlEncodedReader to parse form data, or url query text into a message.
+        /// </summary>
+        public static FormUrlEncodedReader CreateInstance(byte[] bytes)
+        {
+            return new FormUrlEncodedReader(new StreamReader(new MemoryStream(bytes, false), Encoding.UTF8, false));
+        }
+
+        /// <summary>
+        /// Constructs a FormUrlEncodedReader to parse form data, or url query text into a message.
+        /// </summary>
+        public static FormUrlEncodedReader CreateInstance(string text)
+        {
+            return new FormUrlEncodedReader(new StringReader(text));
+        }
+
+        /// <summary>
+        /// Constructs a FormUrlEncodedReader to parse form data, or url query text into a message.
+        /// </summary>
+        public static FormUrlEncodedReader CreateInstance(TextReader input)
+        {
+            return new FormUrlEncodedReader(input);
+        }
+        #endregion
+
+        private bool ReadNext()
+        {
+            StringBuilder field = new StringBuilder(32);
+            StringBuilder value = new StringBuilder(64);
+            int ch;
+            while (-1 != (ch = _input.Read()) && ch != '=' && ch != '&')
+            {
+                field.Append((char)ch);
+            }
+
+            if (ch != -1 && ch != '&')
+            {
+                while (-1 != (ch = _input.Read()) && ch != '&')
+                {
+                    value.Append((char)ch);
+                }
+            }
+
+            _fieldName = field.ToString();
+            _fieldValue = Uri.UnescapeDataString(value.Replace('+', ' ').ToString());
+            
+            return !String.IsNullOrEmpty(_fieldName);
+        }
+
+        /// <summary>
+        /// No-op
+        /// </summary>
+        public override void ReadMessageStart()
+        { }
+
+        /// <summary>
+        /// No-op
+        /// </summary>
+        public override void ReadMessageEnd()
+        { }
+
+        /// <summary>
+        /// Merges the contents of stream into the provided message builder
+        /// </summary>
+        public override TBuilder Merge<TBuilder>(TBuilder builder, ExtensionRegistry registry)
+        {
+            builder.WeakMergeFrom(this, registry);
+            return builder;
+        }
+
+        /// <summary>
+        /// Causes the reader to skip past this field
+        /// </summary>
+        protected override void Skip()
+        {
+            _ready = ReadNext();
+        }
+
+        /// <summary>
+        /// Peeks at the next field in the input stream and returns what information is available.
+        /// </summary>
+        /// <remarks>
+        /// This may be called multiple times without actually reading the field.  Only after the field
+        /// is either read, or skipped, should PeekNext return a different value.
+        /// </remarks>
+        protected override bool PeekNext(out string field)
+        {
+            field = _ready ? _fieldName : null;
+            return field != null;
+        }
+
+        /// <summary>
+        /// Returns true if it was able to read a String from the input
+        /// </summary>
+        protected override bool ReadAsText(ref string value, Type typeInfo)
+        {
+            if (_ready)
+            {
+                value = _fieldValue;
+                _ready = ReadNext();
+                return true;
+            }
+            return false;
+        }
+
+        /// <summary>
+        /// It's unlikely this will work for anything but text data as bytes UTF8 are transformed to text and back to bytes
+        /// </summary>
+        protected override ByteString DecodeBytes(string bytes)
+        { return ByteString.CopyFromUtf8(bytes); }
+
+        /// <summary>
+        /// Not Supported
+        /// </summary>
+        public override bool ReadGroup(IBuilderLite value, ExtensionRegistry registry)
+        { throw new NotSupportedException(); }
+
+        /// <summary>
+        /// Not Supported
+        /// </summary>
+        protected override bool ReadMessage(IBuilderLite builder, ExtensionRegistry registry)
+        { throw new NotSupportedException(); }
+    }
+}

+ 153 - 0
src/ProtocolBuffers.Serialization/Http/MessageFormatFactory.cs

@@ -0,0 +1,153 @@
+using System;
+using System.IO;
+using System.Xml;
+using System.Text;
+
+namespace Google.ProtocolBuffers.Serialization.Http
+{
+    /// <summary>
+    /// Extensions and helpers to abstract the reading/writing of messages by a client-specified content type.
+    /// </summary>
+    public static class MessageFormatFactory
+    {
+        /// <summary>
+        /// Constructs an ICodedInputStream from the input stream based on the contentType provided
+        /// </summary>
+        /// <param name="options">Options specific to reading this message and/or content type</param>
+        /// <param name="contentType">The mime type of the input stream content</param>
+        /// <param name="input">The stream to read the message from</param>
+        /// <returns>The ICodedInputStream that can be given to the IBuilder.MergeFrom(...) method</returns>
+        public static ICodedInputStream CreateInputStream(MessageFormatOptions options, string contentType, Stream input)
+        {
+            ICodedInputStream codedInput = ContentTypeToInputStream(contentType, options, input);
+
+            if (codedInput is XmlFormatReader)
+            {
+                XmlFormatReader reader = (XmlFormatReader)codedInput;
+                reader.RootElementName = options.XmlReaderRootElementName;
+                reader.Options = options.XmlReaderOptions;
+            }
+
+            return codedInput;
+        }
+
+        /// <summary>
+        /// Merges the message from the input stream based on the contentType provided
+        /// </summary>
+        /// <typeparam name="TBuilder">A type derived from IBuilderLite</typeparam>
+        /// <param name="builder">An instance of a message builder</param>
+        /// <param name="options">Options specific to reading this message and/or content type</param>
+        /// <param name="contentType">The mime type of the input stream content</param>
+        /// <param name="input">The stream to read the message from</param>
+        /// <returns>The same builder instance that was supplied in the builder parameter</returns>
+        public static TBuilder MergeFrom<TBuilder>(this TBuilder builder, MessageFormatOptions options, string contentType, Stream input) where TBuilder : IBuilderLite
+        {
+            ICodedInputStream codedInput = CreateInputStream(options, contentType, input);
+            codedInput.ReadMessageStart();
+            builder.WeakMergeFrom(codedInput, options.ExtensionRegistry);
+            codedInput.ReadMessageEnd();
+            return builder;
+        }
+        
+        /// <summary>
+        /// Writes the message instance to the stream using the content type provided
+        /// </summary>
+        /// <param name="options">Options specific to writing this message and/or content type</param>
+        /// <param name="contentType">The mime type of the content to be written</param>
+        /// <param name="output">The stream to write the message to</param>
+        /// <remarks> If you do not dispose of ICodedOutputStream some formats may yield incomplete output </remarks>
+        public static ICodedOutputStream CreateOutputStream(MessageFormatOptions options, string contentType, Stream output)
+        {
+            ICodedOutputStream codedOutput = ContentTypeToOutputStream(contentType, options, output);
+
+            if (codedOutput is JsonFormatWriter)
+            {
+                JsonFormatWriter writer = (JsonFormatWriter)codedOutput;
+                if (options.FormattedOutput)
+                {
+                    writer.Formatted();
+                }
+            }
+            else if (codedOutput is XmlFormatWriter)
+            {
+                XmlFormatWriter writer = (XmlFormatWriter)codedOutput;
+                if (options.FormattedOutput)
+                {
+                    XmlWriterSettings settings = new XmlWriterSettings()
+                                                     {
+                                                         CheckCharacters = false,
+                                                         NewLineHandling = NewLineHandling.Entitize,
+                                                         OmitXmlDeclaration = true,
+                                                         Encoding = new UTF8Encoding(false),
+                                                         Indent = true,
+                                                         IndentChars = "    ",
+                                                         NewLineChars = Environment.NewLine,
+                                                     };
+                    // Don't know how else to change xml writer options?
+                    codedOutput = writer = XmlFormatWriter.CreateInstance(XmlWriter.Create(output, settings));
+                }
+                writer.RootElementName = options.XmlWriterRootElementName;
+                writer.Options = options.XmlWriterOptions;
+            }
+
+            return codedOutput;
+        }
+
+        /// <summary>
+        /// Writes the message instance to the stream using the content type provided
+        /// </summary>
+        /// <param name="message">An instance of a message</param>
+        /// <param name="options">Options specific to writing this message and/or content type</param>
+        /// <param name="contentType">The mime type of the content to be written</param>
+        /// <param name="output">The stream to write the message to</param>
+        public static void WriteTo(this IMessageLite message, MessageFormatOptions options, string contentType, Stream output)
+        {
+            ICodedOutputStream codedOutput = CreateOutputStream(options, contentType, output);
+
+            // Output the appropriate message preamble
+            codedOutput.WriteMessageStart();
+
+            // Write the message content to the output
+            message.WriteTo(codedOutput);
+
+            // Write the closing message fragment
+            codedOutput.WriteMessageEnd();
+            codedOutput.Flush();
+        }
+
+        private static ICodedInputStream ContentTypeToInputStream(string contentType, MessageFormatOptions options, Stream input)
+        {
+            contentType = (contentType ?? String.Empty).Split(';')[0].Trim();
+
+            Converter<Stream, ICodedInputStream> factory;
+            if(!options.MimeInputTypesReadOnly.TryGetValue(contentType, out factory) || factory == null)
+            {
+                if(String.IsNullOrEmpty(options.DefaultContentType) ||
+                    !options.MimeInputTypesReadOnly.TryGetValue(options.DefaultContentType, out factory) || factory == null)
+                {
+                    throw new ArgumentOutOfRangeException("contentType");
+                }
+            }
+
+            return factory(input);
+        }
+
+        private static ICodedOutputStream ContentTypeToOutputStream(string contentType, MessageFormatOptions options, Stream output)
+        {
+            contentType = (contentType ?? String.Empty).Split(';')[0].Trim();
+
+            Converter<Stream, ICodedOutputStream> factory;
+            if (!options.MimeOutputTypesReadOnly.TryGetValue(contentType, out factory) || factory == null)
+            {
+                if (String.IsNullOrEmpty(options.DefaultContentType) ||
+                    !options.MimeOutputTypesReadOnly.TryGetValue(options.DefaultContentType, out factory) || factory == null)
+                {
+                    throw new ArgumentOutOfRangeException("contentType");
+                }
+            }
+
+            return factory(output);
+        }
+
+    }
+}

+ 167 - 0
src/ProtocolBuffers.Serialization/Http/MessageFormatOptions.cs

@@ -0,0 +1,167 @@
+using System;
+using System.IO;
+using System.Collections.Generic;
+using Google.ProtocolBuffers.Collections;
+
+namespace Google.ProtocolBuffers.Serialization.Http
+{
+    /// <summary>
+    /// Defines control information for the various formatting used with HTTP services
+    /// </summary>
+    public class MessageFormatOptions
+    {
+        /// <summary>The mime type for xml content</summary>
+        /// <remarks>Other valid xml mime types include: application/binary, application/x-protobuf</remarks>
+        public const string ContentTypeProtoBuffer = "application/vnd.google.protobuf";
+
+        /// <summary>The mime type for xml content</summary>
+        /// <remarks>Other valid xml mime types include: text/xml</remarks>
+        public const string ContentTypeXml = "application/xml";
+        
+        /// <summary>The mime type for json content</summary>
+        /// <remarks>
+        /// Other valid json mime types include: application/json, application/x-json, 
+        /// application/x-javascript, text/javascript, text/x-javascript, text/x-json, text/json
+        /// </remarks>
+        public const string ContentTypeJson = "application/json";
+
+        /// <summary>The mime type for query strings and x-www-form-urlencoded content</summary>
+        /// <remarks>This mime type is input-only</remarks>
+        public const string ContentFormUrlEncoded = "application/x-www-form-urlencoded";
+
+        /// <summary>
+        /// Default mime-type handling for input
+        /// </summary>
+        private static readonly IDictionary<string, Converter<Stream, ICodedInputStream>> MimeInputDefaults =
+            new ReadOnlyDictionary<string, Converter<Stream, ICodedInputStream>>(
+            new Dictionary<string, Converter<Stream, ICodedInputStream>>(StringComparer.OrdinalIgnoreCase)
+                {
+                    {"application/json", JsonFormatReader.CreateInstance},
+                    {"application/x-json", JsonFormatReader.CreateInstance},
+                    {"application/x-javascript", JsonFormatReader.CreateInstance},
+                    {"text/javascript", JsonFormatReader.CreateInstance},
+                    {"text/x-javascript", JsonFormatReader.CreateInstance},
+                    {"text/x-json", JsonFormatReader.CreateInstance},
+                    {"text/json", JsonFormatReader.CreateInstance},
+                    {"text/xml", XmlFormatReader.CreateInstance},
+                    {"application/xml", XmlFormatReader.CreateInstance},
+                    {"application/binary", CodedInputStream.CreateInstance},
+                    {"application/x-protobuf", CodedInputStream.CreateInstance},
+                    {"application/vnd.google.protobuf", CodedInputStream.CreateInstance},
+                    {"application/x-www-form-urlencoded", FormUrlEncodedReader.CreateInstance},
+                }
+            );
+
+        /// <summary>
+        /// Default mime-type handling for output
+        /// </summary>
+        private static readonly IDictionary<string, Converter<Stream, ICodedOutputStream>> MimeOutputDefaults =
+            new ReadOnlyDictionary<string, Converter<Stream, ICodedOutputStream>>(
+            new Dictionary<string, Converter<Stream, ICodedOutputStream>>(StringComparer.OrdinalIgnoreCase)
+                {
+                    {"application/json", JsonFormatWriter.CreateInstance},
+                    {"application/x-json", JsonFormatWriter.CreateInstance},
+                    {"application/x-javascript", JsonFormatWriter.CreateInstance},
+                    {"text/javascript", JsonFormatWriter.CreateInstance},
+                    {"text/x-javascript", JsonFormatWriter.CreateInstance},
+                    {"text/x-json", JsonFormatWriter.CreateInstance},
+                    {"text/json", JsonFormatWriter.CreateInstance},
+                    {"text/xml", XmlFormatWriter.CreateInstance},
+                    {"application/xml", XmlFormatWriter.CreateInstance},
+                    {"application/binary", CodedOutputStream.CreateInstance},
+                    {"application/x-protobuf", CodedOutputStream.CreateInstance},
+                    {"application/vnd.google.protobuf", CodedOutputStream.CreateInstance},
+                }
+            );
+
+
+
+
+        private string _defaultContentType;
+        private string _xmlReaderRootElementName;
+        private string _xmlWriterRootElementName;
+        private ExtensionRegistry _extensionRegistry;
+        private Dictionary<string, Converter<Stream, ICodedInputStream>> _mimeInputTypes;
+        private Dictionary<string, Converter<Stream, ICodedOutputStream>> _mimeOutputTypes;
+
+        /// <summary> Provides access to modify the mime-type input stream construction </summary>
+        public IDictionary<string, Converter<Stream, ICodedInputStream>> MimeInputTypes
+        {
+            get
+            {
+                return _mimeInputTypes ??
+                    (_mimeInputTypes = new Dictionary<string, Converter<Stream, ICodedInputStream>>(
+                                           MimeInputDefaults, StringComparer.OrdinalIgnoreCase));
+            }
+        }
+
+        /// <summary> Provides access to modify the mime-type input stream construction </summary>
+        public IDictionary<string, Converter<Stream, ICodedOutputStream>> MimeOutputTypes
+        {
+            get
+            {
+                return _mimeOutputTypes ??
+                    (_mimeOutputTypes = new Dictionary<string, Converter<Stream, ICodedOutputStream>>(
+                                           MimeOutputDefaults, StringComparer.OrdinalIgnoreCase));
+            }
+        }
+
+        internal IDictionary<string, Converter<Stream, ICodedInputStream>> MimeInputTypesReadOnly
+        { get { return _mimeInputTypes ?? MimeInputDefaults; } }
+
+        internal IDictionary<string, Converter<Stream, ICodedOutputStream>> MimeOutputTypesReadOnly
+        { get { return _mimeOutputTypes ?? MimeOutputDefaults; } }
+
+        /// <summary>
+        /// The default content type to use if the input type is null or empty.  If this
+        /// value is not supplied an ArgumentOutOfRangeException exception will be raised.
+        /// </summary>
+        public string DefaultContentType
+        {
+            get { return _defaultContentType ?? String.Empty; }
+            set { _defaultContentType = value; }
+        }
+
+        /// <summary>
+        /// The extension registry to use when reading messages
+        /// </summary>
+        public ExtensionRegistry ExtensionRegistry
+        {
+            get { return _extensionRegistry ?? ExtensionRegistry.Empty; }
+            set { _extensionRegistry = value; }
+        }
+
+        /// <summary>
+        /// The name of the xml root element when reading messages
+        /// </summary>
+        public string XmlReaderRootElementName
+        {
+            get { return _xmlReaderRootElementName ?? XmlFormatReader.DefaultRootElementName; }
+            set { _xmlReaderRootElementName = value; }
+        }
+
+        /// <summary>
+        /// Xml reader options
+        /// </summary>
+        public XmlReaderOptions XmlReaderOptions { get; set; }
+
+        /// <summary>
+        /// True to use formatted output including new-lines and default indentation
+        /// </summary>
+        public bool FormattedOutput { get; set; }
+
+        /// <summary>
+        /// The name of the xml root element when writing messages
+        /// </summary>
+        public string XmlWriterRootElementName
+        {
+            get { return _xmlWriterRootElementName ?? XmlFormatWriter.DefaultRootElementName; }
+            set { _xmlWriterRootElementName = value; }
+        }
+
+        /// <summary>
+        /// Xml writer options
+        /// </summary>
+        public XmlWriterOptions XmlWriterOptions { get; set; }
+    }
+}

+ 34 - 0
src/ProtocolBuffers.Serialization/Http/ServiceExtensions.cs

@@ -0,0 +1,34 @@
+using System.Collections.Generic;
+using System.Text;
+using Google.ProtocolBuffers;
+using System.IO;
+
+namespace Google.ProtocolBuffers.Serialization.Http
+{
+    /// <summary>
+    /// Extensions for the IRpcServerStub
+    /// </summary>
+    public static class ServiceExtensions
+    {
+        /// <summary>
+        /// Used to implement a service endpoint on an HTTP server.  This works with services generated with the
+        /// service_generator_type option set to IRPCDISPATCH.
+        /// </summary>
+        /// <param name="stub">The service execution stub</param>
+        /// <param name="methodName">The name of the method being invoked</param>
+        /// <param name="options">optional arguments for the format reader/writer</param>
+        /// <param name="contentType">The mime type for the input stream</param>
+        /// <param name="input">The input stream</param>
+        /// <param name="responseType">The mime type for the output stream</param>
+        /// <param name="output">The output stream</param>
+        public static void HttpCallMethod(this IRpcServerStub stub, string methodName, MessageFormatOptions options, 
+            string contentType, Stream input, string responseType, Stream output)
+        {
+            ICodedInputStream codedInput = MessageFormatFactory.CreateInputStream(options, contentType, input);
+            codedInput.ReadMessageStart();
+            IMessageLite response = stub.CallMethod(methodName, codedInput, options.ExtensionRegistry);
+            codedInput.ReadMessageEnd();
+            response.WriteTo(options, responseType, output);
+        }
+    }
+}

+ 22 - 5
src/ProtocolBuffers.Serialization/JsonFormatReader.cs

@@ -1,4 +1,4 @@
-using System;
+using System;
 using System.Collections.Generic;
 using System.IO;
 using System.Xml;
@@ -11,6 +11,7 @@ namespace Google.ProtocolBuffers.Serialization
     public class JsonFormatReader : AbstractTextReader
     {
         private readonly JsonCursor _input;
+        // The expected token that ends the current item, either ']' or '}'
         private readonly Stack<int> _stopChar;
 
         private enum ReaderState
@@ -101,17 +102,33 @@ namespace Google.ProtocolBuffers.Serialization
         }
 
         /// <summary>
-        /// Merges the contents of stream into the provided message builder
+        /// Reads the root-message preamble specific to this formatter
         /// </summary>
-        public override TBuilder Merge<TBuilder>(TBuilder builder, ExtensionRegistry registry)
+        public override void ReadMessageStart()
         {
             _input.Consume('{');
             _stopChar.Push('}');
 
             _state = ReaderState.BeginObject;
-            builder.WeakMergeFrom(this, registry);
-            _input.Consume((char) _stopChar.Pop());
+        }
+
+        /// <summary>
+        /// Reads the root-message close specific to this formatter
+        /// </summary>
+        public override void ReadMessageEnd()
+        {
+            _input.Consume((char)_stopChar.Pop());
             _state = ReaderState.EndValue;
+        }
+
+        /// <summary>
+        /// Merges the contents of stream into the provided message builder
+        /// </summary>
+        public override TBuilder Merge<TBuilder>(TBuilder builder, ExtensionRegistry registry)
+        {
+            ReadMessageStart();
+            builder.WeakMergeFrom(this, registry);
+            ReadMessageEnd();
             return builder;
         }
 

+ 24 - 4
src/ProtocolBuffers.Serialization/JsonFormatWriter.cs

@@ -1,4 +1,4 @@
-using System;
+using System;
 using System.Collections;
 using System.Collections.Generic;
 using System.IO;
@@ -101,7 +101,7 @@ namespace Google.ProtocolBuffers.Serialization
         private class JsonStreamWriter : JsonFormatWriter
         {
 #if SILVERLIGHT2 || COMPACT_FRAMEWORK_35
-            static readonly Encoding Encoding = Encoding.UTF8;
+            static readonly Encoding Encoding = new UTF8Encoding(false);
 #else
             private static readonly Encoding Encoding = Encoding.ASCII;
 #endif
@@ -168,7 +168,9 @@ namespace Google.ProtocolBuffers.Serialization
 
         #endregion
 
+        //Tracks the writer depth and the array element count at that depth.
         private readonly List<int> _counter;
+        //True if the top-level of the writer is an array as opposed to a single message.
         private bool _isArray;
 
         /// <summary>
@@ -243,7 +245,7 @@ namespace Google.ProtocolBuffers.Serialization
         {
             if (_counter.Count == 0)
             {
-                throw new InvalidOperationException("Missmatched open/close in Json writer.");
+                throw new InvalidOperationException("Mismatched open/close in Json writer.");
             }
 
             int index = _counter.Count - 1;
@@ -444,6 +446,18 @@ namespace Google.ProtocolBuffers.Serialization
         /// Writes the message to the the formatted stream.
         /// </summary>
         public override void WriteMessage(IMessageLite message)
+        {
+            WriteMessageStart();
+            message.WriteTo(this);
+            WriteMessageEnd();
+        }
+
+        /// <summary>
+        /// Used to write the root-message preamble, in json this is the left-curly brace '{'.
+        /// After this call you can call IMessageLite.MergeTo(...) and complete the message with
+        /// a call to WriteMessageEnd().
+        /// </summary>
+        public override void WriteMessageStart()
         {
             if (_isArray)
             {
@@ -451,7 +465,13 @@ namespace Google.ProtocolBuffers.Serialization
             }
             WriteToOutput("{");
             _counter.Add(0);
-            message.WriteTo(this);
+        }
+
+        /// <summary>
+        /// Used to complete a root-message previously started with a call to WriteMessageStart()
+        /// </summary>
+        public override void WriteMessageEnd()
+        {
             _counter.RemoveAt(_counter.Count - 1);
             WriteLine("}");
             Flush();

+ 4 - 0
src/ProtocolBuffers.Serialization/ProtocolBuffers.Serialization.csproj

@@ -98,6 +98,10 @@
   </ItemGroup>
   <ItemGroup>
     <Compile Include="Extensions.cs" />
+    <Compile Include="Http\FormUrlEncodedReader.cs" />
+    <Compile Include="Http\MessageFormatFactory.cs" />
+    <Compile Include="Http\MessageFormatOptions.cs" />
+    <Compile Include="Http\ServiceExtensions.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="AbstractReader.cs" />
     <Compile Include="AbstractTextReader.cs" />

+ 92 - 53
src/ProtocolBuffers.Serialization/XmlFormatReader.cs

@@ -1,7 +1,8 @@
-using System;
+using System;
 using System.Collections.Generic;
 using System.IO;
 using System.Xml;
+using System.Diagnostics;
 
 namespace Google.ProtocolBuffers.Serialization
 {
@@ -14,8 +15,25 @@ namespace Google.ProtocolBuffers.Serialization
     {
         public const string DefaultRootElementName = XmlFormatWriter.DefaultRootElementName;
         private readonly XmlReader _input;
+        // Tracks the message element for each nested message read
+        private readonly Stack<ElementStackEntry> _elements;
+        // The default element name for ReadMessageStart
         private string _rootElementName;
 
+        private struct ElementStackEntry
+        {
+            public readonly string LocalName;
+            public readonly int Depth;
+            public readonly bool IsEmpty;
+
+            public ElementStackEntry(string localName, int depth, bool isEmpty) : this()
+            {
+                LocalName = localName;
+                IsEmpty = isEmpty;
+                Depth = depth;
+            }
+        }
+
         private static XmlReaderSettings DefaultSettings
         {
             get
@@ -72,20 +90,10 @@ namespace Google.ProtocolBuffers.Serialization
         {
             _input = input;
             _rootElementName = DefaultRootElementName;
+            _elements = new Stack<ElementStackEntry>();
             Options = XmlReaderOptions.None;
         }
 
-        /// <summary>
-        /// Constructs the XmlFormatReader with the XmlReader and options
-        /// </summary>
-        protected XmlFormatReader(XmlFormatReader copyFrom, XmlReader input)
-            : base(copyFrom)
-        {
-            _input = input;
-            _rootElementName = copyFrom._rootElementName;
-            Options = copyFrom.Options;
-        }
-
         /// <summary>
         /// Gets or sets the options to use when reading the xml
         /// </summary>
@@ -113,26 +121,61 @@ namespace Google.ProtocolBuffers.Serialization
             }
         }
 
-        private XmlFormatReader CloneWith(XmlReader rdr)
+        [DebuggerNonUserCode]
+        private static void Assert(bool cond)
         {
-            XmlFormatReader copy = new XmlFormatReader(this, rdr);
-            return copy;
+            if (!cond)
+            {
+                throw new FormatException();
+            }
         }
 
-        private void NextElement()
+        /// <summary>
+        /// Reads the root-message preamble specific to this formatter
+        /// </summary>
+        public override void ReadMessageStart()
+        {
+            ReadMessageStart(_rootElementName);
+        }
+
+        /// <summary>
+        /// Reads the root-message preamble specific to this formatter
+        /// </summary>
+        public void ReadMessageStart(string element)
         {
             while (!_input.IsStartElement() && _input.Read())
             {
                 continue;
             }
+            Assert(_input.IsStartElement() && _input.LocalName == element);
+            _elements.Push(new ElementStackEntry(element, _input.Depth, _input.IsEmptyElement));
+            _input.Read();
         }
 
-        private static void Assert(bool cond)
+        /// <summary>
+        /// Reads the root-message close specific to this formatter, MUST be called
+        /// on the reader obtained from ReadMessageStart(string element).
+        /// </summary>
+        public override void ReadMessageEnd()
         {
-            if (!cond)
+            Assert(_elements.Count > 0);
+
+            ElementStackEntry stop = _elements.Peek();
+            while (_input.NodeType != XmlNodeType.EndElement && _input.NodeType != XmlNodeType.Element
+                   && _input.Depth > stop.Depth && _input.Read())
             {
-                throw new FormatException();
+                continue;
+            }
+
+            if (!stop.IsEmpty)
+            {
+                Assert(_input.NodeType == XmlNodeType.EndElement
+                       && _input.LocalName == stop.LocalName
+                       && _input.Depth == stop.Depth);
+
+                _input.Read();
             }
+            _elements.Pop();
         }
 
         /// <summary>
@@ -157,9 +200,9 @@ namespace Google.ProtocolBuffers.Serialization
         public TBuilder Merge<TBuilder>(string element, TBuilder builder, ExtensionRegistry registry)
             where TBuilder : IBuilderLite
         {
-            string field;
-            Assert(PeekNext(out field) && field == element);
-            ReadMessage(builder, registry);
+            ReadMessageStart(element);
+            builder.WeakMergeFrom(this, registry);
+            ReadMessageEnd();
             return builder;
         }
 
@@ -172,7 +215,21 @@ namespace Google.ProtocolBuffers.Serialization
         /// </remarks>
         protected override bool PeekNext(out string field)
         {
-            NextElement();
+            ElementStackEntry stopNode;
+            if (_elements.Count == 0)
+            {
+                stopNode = new ElementStackEntry(null, _input.Depth - 1, false);
+            }
+            else
+            {
+                stopNode = _elements.Peek();
+            }
+
+            while (!_input.IsStartElement() && _input.Depth > stopNode.Depth && _input.Read())
+            {
+                continue;
+            }
+
             if (_input.IsStartElement())
             {
                 field = _input.LocalName;
@@ -235,20 +292,9 @@ namespace Google.ProtocolBuffers.Serialization
         protected override bool ReadMessage(IBuilderLite builder, ExtensionRegistry registry)
         {
             Assert(_input.IsStartElement());
-
-            if (!_input.IsEmptyElement)
-            {
-                int depth = _input.Depth;
-                XmlReader child = _input.ReadSubtree();
-                while (!child.IsStartElement() && child.Read())
-                {
-                    continue;
-                }
-                child.Read();
-                builder.WeakMergeFrom(CloneWith(child), registry);
-                Assert(depth == _input.Depth && _input.NodeType == XmlNodeType.EndElement);
-            }
-            _input.Read();
+            ReadMessageStart(_input.LocalName);
+            builder.WeakMergeFrom(this, registry);
+            ReadMessageEnd();
             return true;
         }
 
@@ -270,27 +316,20 @@ namespace Google.ProtocolBuffers.Serialization
                 {
                     yield return item;
                 }
-                yield break;
             }
-            if (!_input.IsEmptyElement)
+            else
             {
-                int depth = _input.Depth;
-                XmlReader child = _input.ReadSubtree();
-
-                while (!child.IsStartElement() && child.Read())
+                string found;
+                ReadMessageStart(field);
+                if (PeekNext(out found) && found == "item")
                 {
-                    continue;
-                }
-                child.Read();
-
-                foreach (string item in CloneWith(child).NonNestedArrayItems("item"))
-                {
-                    yield return item;
+                    foreach (string item in NonNestedArrayItems("item"))
+                    {
+                        yield return item;
+                    }
                 }
-                Assert(depth == _input.Depth && _input.NodeType == XmlNodeType.EndElement);
+                ReadMessageEnd();
             }
-            _input.Read();
-            yield break;
         }
     }
 }

+ 57 - 20
src/ProtocolBuffers.Serialization/XmlFormatWriter.cs

@@ -1,4 +1,4 @@
-using System;
+using System;
 using System.Collections;
 using System.IO;
 using System.Text;
@@ -14,10 +14,14 @@ namespace Google.ProtocolBuffers.Serialization
     /// </summary>
     public class XmlFormatWriter : AbstractTextWriter
     {
+        private static readonly Encoding DefaultEncoding = new UTF8Encoding(false);
         public const string DefaultRootElementName = "root";
-        private const int NestedArrayFlag = 0x0001;
+
         private readonly XmlWriter _output;
+        // The default element name used for WriteMessageStart
         private string _rootElementName;
+        // Used to assert matching WriteMessageStart/WriteMessageEnd calls
+        private int _messageOpenCount;
 
         private static XmlWriterSettings DefaultSettings(Encoding encoding)
         {
@@ -43,7 +47,7 @@ namespace Google.ProtocolBuffers.Serialization
         /// </summary>
         public static XmlFormatWriter CreateInstance(Stream output)
         {
-            return new XmlFormatWriter(XmlWriter.Create(output, DefaultSettings(Encoding.UTF8)));
+            return new XmlFormatWriter(XmlWriter.Create(output, DefaultSettings(DefaultEncoding)));
         }
 
         /// <summary>
@@ -65,20 +69,10 @@ namespace Google.ProtocolBuffers.Serialization
         protected XmlFormatWriter(XmlWriter output)
         {
             _output = output;
+            _messageOpenCount = 0;
             _rootElementName = DefaultRootElementName;
         }
 
-        /// <summary>
-        /// Closes the underlying XmlTextWriter
-        /// </summary>
-        protected override void Dispose(bool disposing)
-        {
-            if (disposing)
-            {
-                _output.Close();
-            }
-        }
-
         /// <summary>
         /// Gets or sets the default element name to use when using the Merge&lt;TBuilder>()
         /// </summary>
@@ -112,17 +106,30 @@ namespace Google.ProtocolBuffers.Serialization
         }
 
         /// <summary>
-        /// Writes a message as an element using the name defined in <see cref="RootElementName"/>
+        /// Completes any pending write operations
         /// </summary>
-        public override void WriteMessage(IMessageLite message)
+        public override void Flush()
         {
-            WriteMessage(_rootElementName, message);
+            _output.Flush();
+            base.Flush();
         }
 
         /// <summary>
-        /// Writes a message as an element with the given name
+        /// Used to write the root-message preamble, in xml this is open element for RootElementName,
+        /// by default "&lt;root&gt;". After this call you can call IMessageLite.MergeTo(...) and 
+        /// complete the message with a call to WriteMessageEnd().
         /// </summary>
-        public void WriteMessage(string elementName, IMessageLite message)
+        public override void WriteMessageStart()
+        {
+            WriteMessageStart(_rootElementName);
+        }
+
+        /// <summary>
+        /// Used to write the root-message preamble, in xml this is open element for elementName. 
+        /// After this call you can call IMessageLite.MergeTo(...) and  complete the message with 
+        /// a call to WriteMessageEnd().
+        /// </summary>
+        public void WriteMessageStart(string elementName)
         {
             if (TestOption(XmlWriterOptions.OutputJsonTypes))
             {
@@ -133,10 +140,40 @@ namespace Google.ProtocolBuffers.Serialization
             {
                 _output.WriteStartElement(elementName);
             }
+            _messageOpenCount++;
+        }
+
+        /// <summary>
+        /// Used to complete a root-message previously started with a call to WriteMessageStart()
+        /// </summary>
+        public override void WriteMessageEnd()
+        {
+            if (_messageOpenCount <= 0)
+            {
+                throw new InvalidOperationException();
+            }
 
-            message.WriteTo(this);
             _output.WriteEndElement();
             _output.Flush();
+            _messageOpenCount--;
+        }
+
+        /// <summary>
+        /// Writes a message as an element using the name defined in <see cref="RootElementName"/>
+        /// </summary>
+        public override void WriteMessage(IMessageLite message)
+        {
+            WriteMessage(_rootElementName, message);
+        }
+
+        /// <summary>
+        /// Writes a message as an element with the given name
+        /// </summary>
+        public void WriteMessage(string elementName, IMessageLite message)
+        {
+            WriteMessageStart(elementName);
+            message.WriteTo(this);
+            WriteMessageEnd();
         }
 
         /// <summary>

+ 73 - 0
src/ProtocolBuffers.Test/CodedInputStreamTest.cs

@@ -35,6 +35,7 @@
 #endregion
 
 using System;
+using System.Collections.Generic;
 using System.IO;
 using Google.ProtocolBuffers.TestProtos;
 using NUnit.Framework;
@@ -532,5 +533,77 @@ namespace Google.ProtocolBuffers
                 return base.Read(buffer, offset, Math.Min(count, blockSize));
             }
         }
+
+        enum TestNegEnum { None = 0, Value = -2 }
+
+        [Test]
+        public void TestNegativeEnum()
+        {
+            byte[] bytes = new byte[10] { 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01 };
+            CodedInputStream input = CodedInputStream.CreateInstance(bytes);
+            object unk;
+            TestNegEnum val = TestNegEnum.None;
+
+            Assert.IsTrue(input.ReadEnum(ref val, out unk));
+            Assert.IsTrue(input.IsAtEnd);
+            Assert.AreEqual(TestNegEnum.Value, val);
+        }
+
+        [Test]
+        public void TestNegativeEnumPackedArray()
+        {
+            int arraySize = 1 + (10 * 5);
+            int msgSize = 1 + 1 + arraySize;
+            byte[] bytes = new byte[msgSize];
+            CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
+            output.WritePackedInt32Array(8, "", arraySize, new int[] { 0, -1, -2, -3, -4, -5 });
+
+            Assert.AreEqual(0, output.SpaceLeft);
+
+            CodedInputStream input = CodedInputStream.CreateInstance(bytes);
+            uint tag;
+            string name;
+            Assert.IsTrue(input.ReadTag(out tag, out name));
+
+            List<TestNegEnum> values = new List<TestNegEnum>();
+            ICollection<object> unk;
+            input.ReadEnumArray(tag, name, values, out unk);
+
+            Assert.AreEqual(2, values.Count);
+            Assert.AreEqual(TestNegEnum.None, values[0]);
+            Assert.AreEqual(TestNegEnum.Value, values[1]);
+
+            Assert.IsNotNull(unk);
+            Assert.AreEqual(4, unk.Count);
+        }
+
+        [Test]
+        public void TestNegativeEnumArray()
+        {
+            int arraySize = 1 + 1 + (11 * 5);
+            int msgSize = arraySize;
+            byte[] bytes = new byte[msgSize];
+            CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
+            output.WriteInt32Array(8, "", new int[] { 0, -1, -2, -3, -4, -5 });
+
+            Assert.AreEqual(0, output.SpaceLeft);
+
+            CodedInputStream input = CodedInputStream.CreateInstance(bytes);
+            uint tag;
+            string name;
+            Assert.IsTrue(input.ReadTag(out tag, out name));
+
+            List<TestNegEnum> values = new List<TestNegEnum>();
+            ICollection<object> unk;
+            input.ReadEnumArray(tag, name, values, out unk);
+
+            Assert.AreEqual(2, values.Count);
+            Assert.AreEqual(TestNegEnum.None, values[0]);
+            Assert.AreEqual(TestNegEnum.Value, values[1]);
+
+            Assert.IsNotNull(unk);
+            Assert.AreEqual(4, unk.Count);
+        }
+
     }
 }

+ 79 - 0
src/ProtocolBuffers.Test/CodedOutputStreamTest.cs

@@ -34,6 +34,8 @@
 
 #endregion
 
+using System;
+using System.Collections.Generic;
 using System.IO;
 using Google.ProtocolBuffers.TestProtos;
 using NUnit.Framework;
@@ -288,5 +290,82 @@ namespace Google.ProtocolBuffers
             Assert.AreEqual(-75123905439571256L,
                             CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-75123905439571256L)));
         }
+
+        [Test]
+        public void TestNegativeEnumNoTag()
+        {
+            Assert.AreEqual(10, CodedOutputStream.ComputeInt32SizeNoTag(-2));
+            Assert.AreEqual(10, CodedOutputStream.ComputeEnumSizeNoTag(-2));
+
+            byte[] bytes = new byte[10];
+            CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
+            output.WriteEnumNoTag(-2);
+
+            Assert.AreEqual(0, output.SpaceLeft);
+            Assert.AreEqual("FE-FF-FF-FF-FF-FF-FF-FF-FF-01", BitConverter.ToString(bytes));
+        }
+
+        [Test]
+        public void TestNegativeEnumWithTag()
+        {
+            Assert.AreEqual(11, CodedOutputStream.ComputeInt32Size(8, -2));
+            Assert.AreEqual(11, CodedOutputStream.ComputeEnumSize(8, -2));
+
+            byte[] bytes = new byte[11];
+            CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
+            output.WriteEnum(8, "", -2, -2);
+
+            Assert.AreEqual(0, output.SpaceLeft);
+            //fyi, 0x40 == 0x08 << 3 + 0, field num + wire format shift
+            Assert.AreEqual("40-FE-FF-FF-FF-FF-FF-FF-FF-FF-01", BitConverter.ToString(bytes));
+        }
+
+        [Test]
+        public void TestNegativeEnumArrayPacked()
+        {
+            int arraySize = 1 + (10 * 5);
+            int msgSize = 1 + 1 + arraySize;
+            byte[] bytes = new byte[msgSize];
+            CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
+            output.WritePackedEnumArray(8, "", arraySize, new int[] { 0, -1, -2, -3, -4, -5 });
+
+            Assert.AreEqual(0, output.SpaceLeft);
+
+            CodedInputStream input = CodedInputStream.CreateInstance(bytes);
+            uint tag;
+            string name;
+            Assert.IsTrue(input.ReadTag(out tag, out name));
+
+            List<int> values = new List<int>();
+            input.ReadInt32Array(tag, name, values);
+
+            Assert.AreEqual(6, values.Count);
+            for (int i = 0; i > -6; i--)
+                Assert.AreEqual(i, values[Math.Abs(i)]);
+        }
+
+        [Test]
+        public void TestNegativeEnumArray()
+        {
+            int arraySize = 1 + 1 + (11 * 5);
+            int msgSize = arraySize;
+            byte[] bytes = new byte[msgSize];
+            CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
+            output.WriteEnumArray(8, "", new int[] { 0, -1, -2, -3, -4, -5 });
+
+            Assert.AreEqual(0, output.SpaceLeft);
+
+            CodedInputStream input = CodedInputStream.CreateInstance(bytes);
+            uint tag;
+            string name;
+            Assert.IsTrue(input.ReadTag(out tag, out name));
+
+            List<int> values = new List<int>();
+            input.ReadInt32Array(tag, name, values);
+
+            Assert.AreEqual(6, values.Count);
+            for (int i = 0; i > -6; i--)
+                Assert.AreEqual(i, values[Math.Abs(i)]);
+        }
     }
 }

+ 59 - 0
src/ProtocolBuffers.Test/Collections/PopsicleListTest.cs

@@ -35,6 +35,7 @@
 #endregion
 
 using System;
+using System.Collections.Generic;
 using NUnit.Framework;
 
 internal delegate void Action();
@@ -94,6 +95,64 @@ namespace Google.ProtocolBuffers.Collections
             Assert.IsFalse(list.IsReadOnly);
         }
 
+        [Test]
+        public void DoesNotAddNullEnumerable()
+        {
+            PopsicleList<string> list = new PopsicleList<string>();
+            try
+            {
+                list.Add((IEnumerable<string>)null);
+            }
+            catch (ArgumentNullException)
+            { return; }
+
+            Assert.Fail("List should not allow nulls.");
+        }
+
+        [Test]
+        public void DoesNotAddRangeWithNull()
+        {
+            PopsicleList<string> list = new PopsicleList<string>();
+            try
+            {
+                list.Add(new[] { "a", "b", null });
+            }
+            catch (ArgumentNullException)
+            { return; }
+
+            Assert.Fail("List should not allow nulls.");
+        }
+
+        [Test]
+        public void DoesNotAddNull()
+        {
+            PopsicleList<string> list = new PopsicleList<string>();
+            try
+            {
+                list.Add((string)null);
+            }
+            catch (ArgumentNullException)
+            { return; }
+
+            Assert.Fail("List should not allow nulls.");
+        }
+
+        [Test]
+        public void DoesNotSetNull()
+        {
+            PopsicleList<string> list = new PopsicleList<string>();
+            list.Add("a");
+            try
+            {
+                list[0] = null;
+            }
+            catch (ArgumentNullException)
+            { return; }
+
+            Assert.Fail("List should not allow nulls.");
+        }
+
+
         private static void AssertNotSupported(Action action)
         {
             try

+ 18 - 0
src/ProtocolBuffers.Test/Compatibility/JsonCompatibilityTests.cs

@@ -7,6 +7,24 @@ namespace Google.ProtocolBuffers.Compatibility
 {
     [TestFixture]
     public class JsonCompatibilityTests : CompatibilityTests
+    {
+        protected override object SerializeMessage<TMessage, TBuilder>(TMessage message)
+        {
+            StringWriter sw = new StringWriter();
+            JsonFormatWriter.CreateInstance(sw)
+                .WriteMessage(message);
+            return sw.ToString();
+        }
+
+        protected override TBuilder DeserializeMessage<TMessage, TBuilder>(object message, TBuilder builder, ExtensionRegistry registry)
+        {
+            JsonFormatReader.CreateInstance((string)message).Merge(builder);
+            return builder;
+        }
+    }
+
+    [TestFixture]
+    public class JsonCompatibilityFormattedTests : CompatibilityTests
     {
         protected override object SerializeMessage<TMessage, TBuilder>(TMessage message)
         {

+ 21 - 0
src/ProtocolBuffers.Test/Compatibility/XmlCompatibilityTests.cs

@@ -1,4 +1,5 @@
 using System.IO;
+using System.Xml;
 using Google.ProtocolBuffers.Serialization;
 using Google.ProtocolBuffers.TestProtos;
 using NUnit.Framework;
@@ -22,4 +23,24 @@ namespace Google.ProtocolBuffers.Compatibility
             return reader.Merge("root", builder, registry);
         }
     }
+
+    [TestFixture]
+    public class XmlCompatibilityFormattedTests : CompatibilityTests
+    {
+        protected override object SerializeMessage<TMessage, TBuilder>(TMessage message)
+        {
+            StringWriter text = new StringWriter();
+            XmlWriter xwtr = XmlWriter.Create(text, new XmlWriterSettings { Indent = true, IndentChars = "  " });
+
+            XmlFormatWriter writer = XmlFormatWriter.CreateInstance(xwtr).SetOptions(XmlWriterOptions.OutputNestedArrays);
+            writer.WriteMessage("root", message);
+            return text.ToString();
+        }
+
+        protected override TBuilder DeserializeMessage<TMessage, TBuilder>(object message, TBuilder builder, ExtensionRegistry registry)
+        {
+            XmlFormatReader reader = XmlFormatReader.CreateInstance((string)message).SetOptions(XmlReaderOptions.ReadNestedArrays);
+            return reader.Merge("root", builder, registry);
+        }
+    }
 }

+ 102 - 0
src/ProtocolBuffers.Test/DeprecatedMemberTest.cs

@@ -0,0 +1,102 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Text;
+using NUnit.Framework;
+using UnitTest.Issues.TestProtos;
+
+namespace Google.ProtocolBuffers
+{
+    [TestFixture]
+    public class DeprecatedMemberTest
+    {
+        private static void AssertIsDeprecated(ICustomAttributeProvider member)
+        {
+            Assert.IsNotNull(member);
+            Assert.IsTrue(member.IsDefined(typeof(ObsoleteAttribute), false), "Member not obsolete: " + member);
+        }
+
+        [Test]
+        public void TestDepreatedPrimitiveValue()
+        {
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage).GetProperty("HasPrimitiveValue"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage).GetProperty("PrimitiveValue"));
+
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetProperty("HasPrimitiveValue"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetProperty("PrimitiveValue"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("ClearPrimitiveValue"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("SetPrimitiveValue"));
+        }
+        [Test]
+        public void TestDepreatedPrimitiveArray()
+        {
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage).GetProperty("PrimitiveArrayList"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage).GetProperty("PrimitiveArrayCount"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage).GetMethod("GetPrimitiveArray"));
+
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetProperty("PrimitiveArrayList"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetProperty("PrimitiveArrayCount"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("GetPrimitiveArray"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("SetPrimitiveArray"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("AddPrimitiveArray"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("AddRangePrimitiveArray"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("ClearPrimitiveArray"));
+        }
+        [Test]
+        public void TestDepreatedMessageValue()
+        {
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage).GetProperty("HasMessageValue"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage).GetProperty("MessageValue"));
+
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetProperty("HasMessageValue"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetProperty("MessageValue"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("MergeMessageValue"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("ClearMessageValue"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("SetMessageValue", new[] { typeof(DeprecatedChild) }));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("SetMessageValue", new[] { typeof(DeprecatedChild.Builder) }));
+        }
+        [Test]
+        public void TestDepreatedMessageArray()
+        {
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage).GetProperty("MessageArrayList"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage).GetProperty("MessageArrayCount"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage).GetMethod("GetMessageArray"));
+
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetProperty("MessageArrayList"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetProperty("MessageArrayCount"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("GetMessageArray"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("SetMessageArray", new[] { typeof(int), typeof(DeprecatedChild) }));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("SetMessageArray", new[] { typeof(int), typeof(DeprecatedChild.Builder) }));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("AddMessageArray", new[] { typeof(DeprecatedChild) }));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("AddMessageArray", new[] { typeof(DeprecatedChild.Builder) }));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("AddRangeMessageArray"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("ClearMessageArray"));
+        }
+        [Test]
+        public void TestDepreatedEnumValue()
+        {
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage).GetProperty("HasEnumValue"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage).GetProperty("EnumValue"));
+
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetProperty("HasEnumValue"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetProperty("EnumValue"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("ClearEnumValue"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("SetEnumValue"));
+        }
+        [Test]
+        public void TestDepreatedEnumArray()
+        {
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage).GetProperty("EnumArrayList"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage).GetProperty("EnumArrayCount"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage).GetMethod("GetEnumArray"));
+
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetProperty("EnumArrayList"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetProperty("EnumArrayCount"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("GetEnumArray"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("SetEnumArray"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("AddEnumArray"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("AddRangeEnumArray"));
+            AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("ClearEnumArray"));
+        }
+    }
+}

+ 123 - 0
src/ProtocolBuffers.Test/GeneratedBuilderTest.cs

@@ -0,0 +1,123 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Google.ProtocolBuffers.TestProtos;
+using NUnit.Framework;
+
+namespace Google.ProtocolBuffers
+{
+    [TestFixture]
+    public class GeneratedBuilderTest
+    {
+        class OneTimeEnumerator<T> : IEnumerable<T>
+        {
+            readonly T _item;
+            bool _enumerated;
+            public OneTimeEnumerator(T item)
+            {
+                _item = item;
+            }
+            public IEnumerator<T> GetEnumerator()
+            {
+                Assert.IsFalse(_enumerated, "The collection {0} has already been enumerated", GetType());
+                _enumerated = true;
+                yield return _item;
+            }
+            System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+            { return GetEnumerator(); }
+        }
+
+        [Test]
+        public void DoesNotEnumerateTwiceForMessageList()
+        {
+            TestAllTypes.Builder b = new TestAllTypes.Builder();
+            b.AddRangeRepeatedForeignMessage(
+                new OneTimeEnumerator<ForeignMessage>(
+                    ForeignMessage.DefaultInstance));
+        }
+        [Test]
+        public void DoesNotEnumerateTwiceForPrimitiveList()
+        {
+            TestAllTypes.Builder b = new TestAllTypes.Builder();
+            b.AddRangeRepeatedInt32(new OneTimeEnumerator<int>(1));
+        }
+        [Test]
+        public void DoesNotEnumerateTwiceForStringList()
+        {
+            TestAllTypes.Builder b = new TestAllTypes.Builder();
+            b.AddRangeRepeatedString(new OneTimeEnumerator<string>("test"));
+        }
+        [Test]
+        public void DoesNotEnumerateTwiceForEnumList()
+        {
+            TestAllTypes.Builder b = new TestAllTypes.Builder();
+            b.AddRangeRepeatedForeignEnum(new OneTimeEnumerator<ForeignEnum>(ForeignEnum.FOREIGN_BAR));
+        }
+
+        private static void AssertThrows<T>(System.Threading.ThreadStart method) where T : Exception
+        {
+            try
+            {
+                method();
+            }
+            catch (Exception error)
+            {
+                if (error is T)
+                    return;
+                throw;
+            }
+            Assert.Fail("Expected exception of type " + typeof(T));
+        }
+
+        [Test]
+        public void DoesNotAddNullToMessageListByAddRange()
+        {
+            TestAllTypes.Builder b = new TestAllTypes.Builder();
+            AssertThrows<ArgumentNullException>(
+                () => b.AddRangeRepeatedForeignMessage(new ForeignMessage[] { null })
+                    );
+        }
+        [Test]
+        public void DoesNotAddNullToMessageListByAdd()
+        {
+            TestAllTypes.Builder b = new TestAllTypes.Builder();
+            AssertThrows<ArgumentNullException>(
+                () => b.AddRepeatedForeignMessage((ForeignMessage)null)
+                    );
+        }
+        [Test]
+        public void DoesNotAddNullToMessageListBySet()
+        {
+            TestAllTypes.Builder b = new TestAllTypes.Builder();
+            b.AddRepeatedForeignMessage(ForeignMessage.DefaultInstance);
+            AssertThrows<ArgumentNullException>(
+                () => b.SetRepeatedForeignMessage(0, (ForeignMessage)null)
+                    );
+        }
+        [Test]
+        public void DoesNotAddNullToStringListByAddRange()
+        {
+            TestAllTypes.Builder b = new TestAllTypes.Builder();
+            AssertThrows<ArgumentNullException>(
+                () => b.AddRangeRepeatedString(new String[] { null })
+                    );
+        }
+        [Test]
+        public void DoesNotAddNullToStringListByAdd()
+        {
+            TestAllTypes.Builder b = new TestAllTypes.Builder();
+            AssertThrows<ArgumentNullException>(
+                () => b.AddRepeatedString(null)
+                    );
+        }
+        [Test]
+        public void DoesNotAddNullToStringListBySet()
+        {
+            TestAllTypes.Builder b = new TestAllTypes.Builder();
+            b.AddRepeatedString("one");
+            AssertThrows<ArgumentNullException>(
+                () => b.SetRepeatedString(0, null)
+                    );
+        }
+    }
+}

+ 0 - 16
src/ProtocolBuffers.Test/GeneratedMessageTest.cs

@@ -111,22 +111,6 @@ namespace Google.ProtocolBuffers
             }
         }
 
-        [Test]
-        public void DoubleBuildError()
-        {
-            TestAllTypes.Builder builder = new TestAllTypes.Builder();
-            builder.Build();
-            try
-            {
-                builder.Build();
-                Assert.Fail("Should have thrown exception.");
-            }
-            catch (InvalidOperationException)
-            {
-                // Success.
-            }
-        }
-
         [Test]
         public void DefaultInstance()
         {

+ 1 - 1
src/ProtocolBuffers.Test/Properties/AssemblyInfo.cs

@@ -12,7 +12,7 @@ using System.Runtime.InteropServices;
 [assembly: AssemblyConfiguration("")]
 [assembly: AssemblyCompany("")]
 [assembly: AssemblyProduct("ProtocolBuffers.Test")]
-[assembly: AssemblyCopyright("Copyright ©  2008")]
+[assembly: AssemblyCopyright("Copyright �  2008")]
 [assembly: AssemblyTrademark("")]
 [assembly: AssemblyCulture("")]
 

+ 7 - 4
src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj

@@ -45,9 +45,7 @@
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
     <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
-    <DocumentationFile>bin\Debug\Google.ProtocolBuffers.Test.XML</DocumentationFile>
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
-    <NoWarn>1591</NoWarn>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
     <DebugType>pdbonly</DebugType>
@@ -57,9 +55,7 @@
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
     <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
-    <DocumentationFile>bin\Release\Google.ProtocolBuffers.Test.XML</DocumentationFile>
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
-    <NoWarn>1591</NoWarn>
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="nunit.framework, Version=2.2.8.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77">
@@ -92,11 +88,15 @@
     </Compile>
     <Compile Include="Compatibility\TextCompatibilityTests.cs" />
     <Compile Include="Compatibility\XmlCompatibilityTests.cs" />
+    <Compile Include="TestRpcForMimeTypes.cs" />
+    <Compile Include="TestReaderForUrlEncoded.cs" />
     <Compile Include="CSharpOptionsTest.cs" />
+    <Compile Include="DeprecatedMemberTest.cs" />
     <Compile Include="DescriptorsTest.cs" />
     <Compile Include="Descriptors\MessageDescriptorTest.cs" />
     <Compile Include="DynamicMessageTest.cs" />
     <Compile Include="ExtendableMessageTest.cs" />
+    <Compile Include="GeneratedBuilderTest.cs" />
     <Compile Include="GeneratedMessageTest.cs" />
     <Compile Include="MessageStreamIteratorTest.cs" />
     <Compile Include="MessageStreamWriterTest.cs" />
@@ -105,8 +105,11 @@
     <Compile Include="NameHelpersTest.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="ReflectionTester.cs" />
+    <Compile Include="ReusableBuilderTest.cs" />
     <Compile Include="SerializableTest.cs" />
     <Compile Include="ServiceTest.cs" />
+    <Compile Include="TestCornerCases.cs" />
+    <Compile Include="TestMimeMessageFormats.cs" />
     <Compile Include="TestProtos\UnitTestCSharpOptionsProtoFile.cs" />
     <Compile Include="TestProtos\UnitTestCustomOptionsProtoFile.cs" />
     <Compile Include="TestProtos\UnitTestEmbedOptimizeForProtoFile.cs" />

+ 170 - 0
src/ProtocolBuffers.Test/ReusableBuilderTest.cs

@@ -0,0 +1,170 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Text;
+using Google.ProtocolBuffers.Collections;
+using NUnit.Framework;
+using Google.ProtocolBuffers.TestProtos;
+using Google.ProtocolBuffers.Serialization;
+using UnitTest.Issues.TestProtos;
+
+namespace Google.ProtocolBuffers
+{
+    [TestFixture]
+    public class ReusableBuilderTest
+    {
+        [Test, Description("Issue 28: Circular message dependencies result in null defaults for DefaultInstance")]
+        public void EnsureStaticCicularReference()
+        {
+            MyMessageAReferenceB ab = MyMessageAReferenceB.DefaultInstance;
+            Assert.IsNotNull(ab);
+            Assert.IsNotNull(ab.Value);
+            MyMessageBReferenceA ba = MyMessageBReferenceA.DefaultInstance;
+            Assert.IsNotNull(ba);
+            Assert.IsNotNull(ba.Value);
+        }
+
+        [Test]
+        public void TestModifyDefaultInstance()
+        {
+            //verify that the default instance has correctly been marked as read-only
+            Assert.AreEqual(typeof(PopsicleList<bool>), TestAllTypes.DefaultInstance.RepeatedBoolList.GetType());
+            PopsicleList<bool> list = (PopsicleList<bool>)TestAllTypes.DefaultInstance.RepeatedBoolList;
+            Assert.IsTrue(list.IsReadOnly);
+        }
+
+        [Test]
+        public void TestUnmodifiedDefaultInstance()
+        {
+            //Simply calling ToBuilder().Build() no longer creates a copy of the message
+            TestAllTypes.Builder builder = TestAllTypes.DefaultInstance.ToBuilder();
+            Assert.IsTrue(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+        }
+
+        [Test]
+        public void BuildMultipleWithoutChange()
+        {
+            //Calling Build() or BuildPartial() does not require a copy of the message
+            TestAllTypes.Builder builder = TestAllTypes.DefaultInstance.ToBuilder();
+            builder.SetDefaultBool(true);
+
+            TestAllTypes first = builder.BuildPartial();
+            //Still the same instance?
+            Assert.IsTrue(ReferenceEquals(first, builder.Build()));
+            //Still the same instance?
+            Assert.IsTrue(ReferenceEquals(first, builder.BuildPartial().ToBuilder().Build()));
+        }
+
+        [Test]
+        public void MergeFromDefaultInstance()
+        {
+            TestAllTypes.Builder builder = TestAllTypes.DefaultInstance.ToBuilder();
+            Assert.IsTrue(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+            builder.MergeFrom(TestAllTypes.DefaultInstance);
+            Assert.IsTrue(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+        }
+
+        [Test]
+        public void BuildNewBuilderIsDefaultInstance()
+        {
+            Assert.IsTrue(ReferenceEquals(TestAllTypes.DefaultInstance, new TestAllTypes.Builder().Build()));
+            Assert.IsTrue(ReferenceEquals(TestAllTypes.DefaultInstance, TestAllTypes.CreateBuilder().Build()));
+            //last test, if you clear a builder it reverts to default instance
+            Assert.IsTrue(ReferenceEquals(TestAllTypes.DefaultInstance,
+                TestAllTypes.CreateBuilder().SetOptionalBool(true).Build().ToBuilder().Clear().Build()));
+        }
+
+        [Test]
+        public void BuildModifyAndRebuild()
+        {
+            TestAllTypes.Builder b1 = new TestAllTypes.Builder();
+            b1.SetDefaultInt32(1);
+            b1.AddRepeatedInt32(2);
+            b1.SetOptionalForeignMessage(ForeignMessage.DefaultInstance);
+
+            TestAllTypes m1 = b1.Build();
+
+            b1.SetDefaultInt32(5);
+            b1.AddRepeatedInt32(6);
+            b1.SetOptionalForeignMessage(b1.OptionalForeignMessage.ToBuilder().SetC(7));
+
+            TestAllTypes m2 = b1.Build();
+            
+            Assert.AreEqual("{\"optional_foreign_message\":{},\"repeated_int32\":[2],\"default_int32\":1}", m1.ToJson());
+            Assert.AreEqual("{\"optional_foreign_message\":{\"c\":7},\"repeated_int32\":[2,6],\"default_int32\":5}", m2.ToJson());
+        }
+
+        [Test]
+        public void CloneOnChangePrimitive()
+        {
+            TestAllTypes.Builder builder = TestAllTypes.DefaultInstance.ToBuilder();
+            Assert.IsTrue(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+            builder.SetDefaultBool(true);
+            Assert.IsFalse(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+        }
+
+        [Test]
+        public void CloneOnAddRepeatedBool()
+        {
+            TestAllTypes.Builder builder = TestAllTypes.DefaultInstance.ToBuilder();
+            Assert.IsTrue(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+            builder.AddRepeatedBool(true);
+            Assert.IsFalse(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+        }
+
+        [Test]
+        public void CloneOnGetRepeatedBoolList()
+        {
+            TestAllTypes.Builder builder = TestAllTypes.DefaultInstance.ToBuilder();
+            Assert.IsTrue(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+            GC.KeepAlive(builder.RepeatedBoolList);
+            Assert.IsFalse(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+        }
+
+        [Test]
+        public void CloneOnChangeMessage()
+        {
+            TestAllTypes.Builder builder = TestAllTypes.DefaultInstance.ToBuilder();
+            Assert.IsTrue(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+            builder.SetOptionalForeignMessage(new ForeignMessage.Builder());
+            Assert.IsFalse(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+        }
+
+        [Test]
+        public void CloneOnClearMessage()
+        {
+            TestAllTypes.Builder builder = TestAllTypes.DefaultInstance.ToBuilder();
+            Assert.IsTrue(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+            builder.ClearOptionalForeignMessage();
+            Assert.IsFalse(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+        }
+
+        [Test]
+        public void CloneOnGetRepeatedForeignMessageList()
+        {
+            TestAllTypes.Builder builder = TestAllTypes.DefaultInstance.ToBuilder();
+            Assert.IsTrue(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+            GC.KeepAlive(builder.RepeatedForeignMessageList);
+            Assert.IsFalse(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+        }
+
+        [Test]
+        public void CloneOnChangeEnumValue()
+        {
+            TestAllTypes.Builder builder = TestAllTypes.DefaultInstance.ToBuilder();
+            Assert.IsTrue(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+            builder.SetOptionalForeignEnum(ForeignEnum.FOREIGN_BAR);
+            Assert.IsFalse(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+        }
+
+        [Test]
+        public void CloneOnGetRepeatedForeignEnumList()
+        {
+            TestAllTypes.Builder builder = TestAllTypes.DefaultInstance.ToBuilder();
+            Assert.IsTrue(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+            GC.KeepAlive(builder.RepeatedForeignEnumList);
+            Assert.IsFalse(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+        }
+
+    }
+}

+ 36 - 12
src/ProtocolBuffers.Test/SerializableTest.cs

@@ -31,9 +31,15 @@ namespace Google.ProtocolBuffers
                 .AddNumbers(1)
                 .AddNumbers(2)
                 .AddNumbers(3)
-                .SetChild(TestXmlChild.CreateBuilder().AddOptions(EnumOptions.ONE).SetBinary(ByteString.CopyFrom(new byte[1])))
-                .AddChildren(TestXmlMessage.Types.Children.CreateBuilder().AddOptions(EnumOptions.TWO).SetBinary(ByteString.CopyFrom(new byte[2])))
-                .AddChildren(TestXmlMessage.Types.Children.CreateBuilder().AddOptions(EnumOptions.THREE).SetBinary(ByteString.CopyFrom(new byte[3])))
+                .SetChild(TestXmlChild.CreateBuilder()
+                                      .AddOptions(EnumOptions.ONE)
+                                      .SetBinary(ByteString.CopyFrom(new byte[1])))
+                .AddChildren(TestXmlMessage.Types.Children.CreateBuilder()
+                                                          .AddOptions(EnumOptions.TWO)
+                                                          .SetBinary(ByteString.CopyFrom(new byte[2])))
+                .AddChildren(TestXmlMessage.Types.Children.CreateBuilder()
+                                                          .AddOptions(EnumOptions.THREE)
+                                                          .SetBinary(ByteString.CopyFrom(new byte[3])))
                 .Build();
 
             MemoryStream ms = new MemoryStream();
@@ -58,9 +64,15 @@ namespace Google.ProtocolBuffers
                 .AddNumbers(1)
                 .AddNumbers(2)
                 .AddNumbers(3)
-                .SetChild(TestXmlChild.CreateBuilder().AddOptions(EnumOptions.ONE).SetBinary(ByteString.CopyFrom(new byte[1])))
-                .AddChildren(TestXmlMessage.Types.Children.CreateBuilder().AddOptions(EnumOptions.TWO).SetBinary(ByteString.CopyFrom(new byte[2])))
-                .AddChildren(TestXmlMessage.Types.Children.CreateBuilder().AddOptions(EnumOptions.THREE).SetBinary(ByteString.CopyFrom(new byte[3])))
+                .SetChild(TestXmlChild.CreateBuilder()
+                                      .AddOptions(EnumOptions.ONE)
+                                      .SetBinary(ByteString.CopyFrom(new byte[1])))
+                .AddChildren(TestXmlMessage.Types.Children.CreateBuilder()
+                                                          .AddOptions(EnumOptions.TWO)
+                                                          .SetBinary(ByteString.CopyFrom(new byte[2])))
+                .AddChildren(TestXmlMessage.Types.Children.CreateBuilder()
+                                                          .AddOptions(EnumOptions.THREE)
+                                                          .SetBinary(ByteString.CopyFrom(new byte[3])))
                 .SetExtension(UnitTestXmlSerializerTestProtoFile.ExtensionText, " extension text value ! ")
                 .SetExtension(UnitTestXmlSerializerTestProtoFile.ExtensionMessage, new TestXmlExtension.Builder().SetNumber(42).Build())
                 .AddExtension(UnitTestXmlSerializerTestProtoFile.ExtensionNumber, 100)
@@ -97,9 +109,15 @@ namespace Google.ProtocolBuffers
                 .AddNumbers(1)
                 .AddNumbers(2)
                 .AddNumbers(3)
-                .SetChild(TestXmlChild.CreateBuilder().AddOptions(EnumOptions.ONE).SetBinary(ByteString.CopyFrom(new byte[1])))
-                .AddChildren(TestXmlMessage.Types.Children.CreateBuilder().AddOptions(EnumOptions.TWO).SetBinary(ByteString.CopyFrom(new byte[2])))
-                .AddChildren(TestXmlMessage.Types.Children.CreateBuilder().AddOptions(EnumOptions.THREE).SetBinary(ByteString.CopyFrom(new byte[3])))
+                .SetChild(TestXmlChild.CreateBuilder()
+                                      .AddOptions(EnumOptions.ONE)
+                                      .SetBinary(ByteString.CopyFrom(new byte[1])))
+                .AddChildren(TestXmlMessage.Types.Children.CreateBuilder()
+                                                          .AddOptions(EnumOptions.TWO)
+                                                          .SetBinary(ByteString.CopyFrom(new byte[2])))
+                .AddChildren(TestXmlMessage.Types.Children.CreateBuilder()
+                                                          .AddOptions(EnumOptions.THREE)
+                                                          .SetBinary(ByteString.CopyFrom(new byte[3])))
                 ;
 
             MemoryStream ms = new MemoryStream();
@@ -124,9 +142,15 @@ namespace Google.ProtocolBuffers
                 .AddNumbers(1)
                 .AddNumbers(2)
                 .AddNumbers(3)
-                .SetChild(TestXmlChild.CreateBuilder().AddOptions(EnumOptions.ONE).SetBinary(ByteString.CopyFrom(new byte[1])))
-                .AddChildren(TestXmlMessage.Types.Children.CreateBuilder().AddOptions(EnumOptions.TWO).SetBinary(ByteString.CopyFrom(new byte[2])))
-                .AddChildren(TestXmlMessage.Types.Children.CreateBuilder().AddOptions(EnumOptions.THREE).SetBinary(ByteString.CopyFrom(new byte[3])))
+                .SetChild(TestXmlChild.CreateBuilder()
+                                      .AddOptions(EnumOptions.ONE)
+                                      .SetBinary(ByteString.CopyFrom(new byte[1])))
+                .AddChildren(TestXmlMessage.Types.Children.CreateBuilder()
+                                                          .AddOptions(EnumOptions.TWO)
+                                                          .SetBinary(ByteString.CopyFrom(new byte[2])))
+                .AddChildren(TestXmlMessage.Types.Children.CreateBuilder()
+                                                          .AddOptions(EnumOptions.THREE)
+                                                          .SetBinary(ByteString.CopyFrom(new byte[3])))
                 .SetExtension(UnitTestXmlSerializerTestProtoFile.ExtensionText, " extension text value ! ")
                 .SetExtension(UnitTestXmlSerializerTestProtoFile.ExtensionMessage, new TestXmlExtension.Builder().SetNumber(42).Build())
                 .AddExtension(UnitTestXmlSerializerTestProtoFile.ExtensionNumber, 100)

+ 38 - 0
src/ProtocolBuffers.Test/TestCornerCases.cs

@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using NUnit.Framework;
+using UnitTest.Issues.TestProtos;
+
+namespace Google.ProtocolBuffers
+{
+    [TestFixture]
+    public class TestCornerCases
+    {
+        [Test]
+        public void TestRoundTripNegativeEnums()
+        {
+            NegativeEnumMessage msg = NegativeEnumMessage.CreateBuilder()
+                .SetValue(NegativeEnum.MinusOne) //11
+                .AddValues(NegativeEnum.Zero) //2
+                .AddValues(NegativeEnum.MinusOne) //11
+                .AddValues(NegativeEnum.FiveBelow) //11
+                //2
+                .AddPackedValues(NegativeEnum.Zero) //1
+                .AddPackedValues(NegativeEnum.MinusOne) //10
+                .AddPackedValues(NegativeEnum.FiveBelow) //10
+                .Build();
+
+            Assert.AreEqual(58, msg.SerializedSize);
+
+            byte[] bytes = new byte[58];
+            CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
+
+            msg.WriteTo(output);
+            Assert.AreEqual(0, output.SpaceLeft);
+
+            NegativeEnumMessage copy = NegativeEnumMessage.ParseFrom(bytes);
+            Assert.AreEqual(msg, copy);
+        }
+    }
+}

+ 264 - 0
src/ProtocolBuffers.Test/TestMimeMessageFormats.cs

@@ -0,0 +1,264 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using Google.ProtocolBuffers.Serialization;
+using Google.ProtocolBuffers.Serialization.Http;
+using Google.ProtocolBuffers.TestProtos;
+using NUnit.Framework;
+
+namespace Google.ProtocolBuffers
+{
+    [TestFixture]
+    public class TestMimeMessageFormats
+    {
+        // There is a whole host of various json mime types in use around the net, this is the set we accept...
+        readonly IEnumerable<string> JsonTypes = new string[] { "application/json", "application/x-json", "application/x-javascript", "text/javascript", "text/x-javascript", "text/x-json", "text/json" };
+        readonly IEnumerable<string> XmlTypes = new string[] { "text/xml", "application/xml" };
+        readonly IEnumerable<string> ProtobufTypes = new string[] { "application/binary", "application/x-protobuf", "application/vnd.google.protobuf" };
+
+        [Test]
+        public void TestReadJsonMimeTypes()
+        {
+            foreach (string type in JsonTypes)
+            {
+                Assert.IsTrue(
+                    MessageFormatFactory.CreateInputStream(new MessageFormatOptions(), type, Stream.Null)
+                    is JsonFormatReader);
+            }
+            Assert.IsTrue(
+                MessageFormatFactory.CreateInputStream(new MessageFormatOptions() { DefaultContentType = "application/json" }, null, Stream.Null)
+                is JsonFormatReader);
+        }
+        [Test]
+        public void TestWriteJsonMimeTypes()
+        {
+            foreach (string type in JsonTypes)
+            {
+                Assert.IsTrue(
+                    MessageFormatFactory.CreateOutputStream(new MessageFormatOptions(), type, Stream.Null)
+                    is JsonFormatWriter);
+            }
+            Assert.IsTrue(
+                MessageFormatFactory.CreateOutputStream(new MessageFormatOptions() { DefaultContentType = "application/json" }, null, Stream.Null)
+                is JsonFormatWriter);
+        }
+        [Test]
+        public void TestReadXmlMimeTypes()
+        {
+            foreach (string type in XmlTypes)
+            {
+                Assert.IsTrue(
+                    MessageFormatFactory.CreateInputStream(new MessageFormatOptions(), type, Stream.Null)
+                    is XmlFormatReader);
+            }
+            Assert.IsTrue(
+                MessageFormatFactory.CreateInputStream(new MessageFormatOptions() { DefaultContentType = "application/xml" }, null, Stream.Null)
+                is XmlFormatReader);
+        }
+        [Test]
+        public void TestWriteXmlMimeTypes()
+        {
+            foreach (string type in XmlTypes)
+            {
+                Assert.IsTrue(
+                    MessageFormatFactory.CreateOutputStream(new MessageFormatOptions(), type, Stream.Null)
+                    is XmlFormatWriter);
+            }
+            Assert.IsTrue(
+                MessageFormatFactory.CreateOutputStream(new MessageFormatOptions() { DefaultContentType = "application/xml" }, null, Stream.Null)
+                is XmlFormatWriter);
+        }
+        [Test]
+        public void TestReadProtoMimeTypes()
+        {
+            foreach (string type in ProtobufTypes)
+            {
+                Assert.IsTrue(
+                    MessageFormatFactory.CreateInputStream(new MessageFormatOptions(), type, Stream.Null)
+                    is CodedInputStream);
+            }
+            Assert.IsTrue(
+                MessageFormatFactory.CreateInputStream(new MessageFormatOptions() { DefaultContentType = "application/vnd.google.protobuf" }, null, Stream.Null)
+                is CodedInputStream);
+        }
+        [Test]
+        public void TestWriteProtoMimeTypes()
+        {
+            foreach (string type in ProtobufTypes)
+            {
+                Assert.IsTrue(
+                    MessageFormatFactory.CreateOutputStream(new MessageFormatOptions(), type, Stream.Null)
+                    is CodedOutputStream);
+            }
+            Assert.IsTrue(
+                MessageFormatFactory.CreateOutputStream(new MessageFormatOptions() { DefaultContentType = "application/vnd.google.protobuf" }, null, Stream.Null)
+                is CodedOutputStream);
+        }
+        [Test]
+        public void TestMergeFromJsonType()
+        {
+            TestXmlMessage msg = new TestXmlMessage.Builder().MergeFrom(
+                new MessageFormatOptions(), "application/json", new MemoryStream(Encoding.ASCII.GetBytes(
+                    TestXmlMessage.CreateBuilder().SetText("a").SetNumber(1).Build().ToJson()
+                    )))
+                .Build();
+            Assert.AreEqual("a", msg.Text);
+            Assert.AreEqual(1, msg.Number);
+        }
+        [Test]
+        public void TestMergeFromXmlType()
+        {
+            TestXmlMessage msg = new TestXmlMessage.Builder().MergeFrom(
+                new MessageFormatOptions(), "application/xml", new MemoryStream(Encoding.ASCII.GetBytes(
+                    TestXmlMessage.CreateBuilder().SetText("a").SetNumber(1).Build().ToXml()
+                    )))
+                .Build();
+            Assert.AreEqual("a", msg.Text);
+            Assert.AreEqual(1, msg.Number);
+        }
+        [Test]
+        public void TestMergeFromProtoType()
+        {
+            TestXmlMessage msg = new TestXmlMessage.Builder().MergeFrom(
+                new MessageFormatOptions(), "application/vnd.google.protobuf", new MemoryStream(
+                    TestXmlMessage.CreateBuilder().SetText("a").SetNumber(1).Build().ToByteArray()
+                    ))
+                .Build();
+            Assert.AreEqual("a", msg.Text);
+            Assert.AreEqual(1, msg.Number);
+        }
+        [Test]
+        public void TestWriteToJsonType()
+        {
+            MemoryStream ms = new MemoryStream();
+            TestXmlMessage.CreateBuilder().SetText("a").SetNumber(1).Build()
+                .WriteTo(new MessageFormatOptions(), "application/json", ms);
+
+            Assert.AreEqual(@"{""text"":""a"",""number"":1}", Encoding.UTF8.GetString(ms.ToArray()));
+        }
+        [Test]
+        public void TestWriteToXmlType()
+        {
+            MemoryStream ms = new MemoryStream();
+            TestXmlMessage.CreateBuilder().SetText("a").SetNumber(1).Build()
+                .WriteTo(new MessageFormatOptions(), "application/xml", ms);
+
+            Assert.AreEqual("<root><text>a</text><number>1</number></root>", Encoding.UTF8.GetString(ms.ToArray()));
+        }
+        [Test]
+        public void TestWriteToProtoType()
+        {
+            MemoryStream ms = new MemoryStream();
+            TestXmlMessage.CreateBuilder().SetText("a").SetNumber(1).Build()
+                .WriteTo(new MessageFormatOptions(), "application/vnd.google.protobuf", ms);
+
+            byte[] bytes = TestXmlMessage.CreateBuilder().SetText("a").SetNumber(1).Build().ToByteArray();
+            Assert.AreEqual(bytes, ms.ToArray());
+        }
+        [Test]
+        public void TestXmlReaderOptions()
+        {
+            MemoryStream ms = new MemoryStream();
+            XmlFormatWriter.CreateInstance(ms)
+                .SetOptions(XmlWriterOptions.OutputNestedArrays)
+                .WriteMessage("my-root-node", TestXmlMessage.CreateBuilder().SetText("a").AddNumbers(1).AddNumbers(2).Build());
+            ms.Position = 0;
+
+            MessageFormatOptions options = new MessageFormatOptions()
+            {
+                XmlReaderOptions = XmlReaderOptions.ReadNestedArrays,
+                XmlReaderRootElementName = "my-root-node"
+            };
+
+            TestXmlMessage msg = new TestXmlMessage.Builder().MergeFrom(
+                options, "application/xml", ms)
+                .Build();
+
+            Assert.AreEqual("a", msg.Text);
+            Assert.AreEqual(1, msg.NumbersList[0]);
+            Assert.AreEqual(2, msg.NumbersList[1]);
+
+        }
+        [Test]
+        public void TestXmlWriterOptions()
+        {
+            TestXmlMessage message = TestXmlMessage.CreateBuilder().SetText("a").AddNumbers(1).AddNumbers(2).Build();
+            MessageFormatOptions options = new MessageFormatOptions()
+            {
+                XmlWriterOptions = XmlWriterOptions.OutputNestedArrays,
+                XmlWriterRootElementName = "root-node"
+            };
+
+            MemoryStream ms = new MemoryStream();
+            message.WriteTo(options, "application/xml", ms);
+            ms.Position = 0;
+            
+            TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder();
+            XmlFormatReader.CreateInstance(ms)
+                .SetOptions(XmlReaderOptions.ReadNestedArrays)
+                .Merge("root-node", builder);
+
+            Assert.AreEqual("a", builder.Text);
+            Assert.AreEqual(1, builder.NumbersList[0]);
+            Assert.AreEqual(2, builder.NumbersList[1]);
+        }
+        [Test]
+        public void TestJsonFormatted()
+        {
+            MemoryStream ms = new MemoryStream();
+            TestXmlMessage.CreateBuilder().SetText("a").SetNumber(1).Build()
+                .WriteTo(new MessageFormatOptions() { FormattedOutput = true }, "application/json", ms);
+
+            Assert.AreEqual("{\r\n    \"text\": \"a\",\r\n    \"number\": 1\r\n}", Encoding.UTF8.GetString(ms.ToArray()));
+        }
+        [Test]
+        public void TestXmlFormatted()
+        {
+            MemoryStream ms = new MemoryStream();
+            TestXmlMessage.CreateBuilder().SetText("a").SetNumber(1).Build()
+                .WriteTo(new MessageFormatOptions() { FormattedOutput = true }, "application/xml", ms);
+
+            Assert.AreEqual("<root>\r\n    <text>a</text>\r\n    <number>1</number>\r\n</root>", Encoding.UTF8.GetString(ms.ToArray()));
+        }
+
+        [Test]
+        public void TestReadCustomMimeTypes()
+        {
+            var options = new MessageFormatOptions();
+            //Remove existing mime-type mappings
+            options.MimeInputTypes.Clear();
+            //Add our own
+            options.MimeInputTypes.Add("-custom-XML-mime-type-", XmlFormatReader.CreateInstance);
+            Assert.AreEqual(1, options.MimeInputTypes.Count);
+
+            Stream xmlStream = new MemoryStream(Encoding.ASCII.GetBytes(
+                TestXmlMessage.CreateBuilder().SetText("a").SetNumber(1).Build().ToXml()
+                                                    ));
+
+            TestXmlMessage msg = new TestXmlMessage.Builder().MergeFrom(
+                options, "-custom-XML-mime-type-", xmlStream)
+                .Build();
+            Assert.AreEqual("a", msg.Text);
+            Assert.AreEqual(1, msg.Number);
+        }
+
+        [Test]
+        public void TestWriteToCustomType()
+        {
+            var options = new MessageFormatOptions();
+            //Remove existing mime-type mappings
+            options.MimeOutputTypes.Clear();
+            //Add our own
+            options.MimeOutputTypes.Add("-custom-XML-mime-type-", XmlFormatWriter.CreateInstance);
+            
+            Assert.AreEqual(1, options.MimeOutputTypes.Count);
+
+            MemoryStream ms = new MemoryStream();
+            TestXmlMessage.CreateBuilder().SetText("a").SetNumber(1).Build()
+                .WriteTo(options, "-custom-XML-mime-type-", ms);
+
+            Assert.AreEqual("<root><text>a</text><number>1</number></root>", Encoding.UTF8.GetString(ms.ToArray()));
+        }
+    }
+}

+ 53 - 14
src/ProtocolBuffers.Test/TestProtos/UnitTestCSharpOptionsProtoFile.cs

@@ -1,5 +1,5 @@
 // Generated by ProtoGen, Version=2.3.0.277, Culture=neutral, PublicKeyToken=17b3b1f090c3ea48.  DO NOT EDIT!
-#pragma warning disable 1591
+#pragma warning disable 1591, 0612
 #region Designer generated code
 
 using pb = global::Google.ProtocolBuffers;
@@ -60,7 +60,8 @@ namespace Google.ProtocolBuffers.TestProtos {
   [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
   [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
   public sealed partial class OptionsMessage : pb::GeneratedMessage<OptionsMessage, OptionsMessage.Builder> {
-    private static readonly OptionsMessage defaultInstance = new Builder().BuildPartial();
+    private OptionsMessage() { }
+    private static readonly OptionsMessage defaultInstance = new OptionsMessage().MakeReadOnly();
     private static readonly string[] _optionsMessageFieldNames = new string[] { "customized", "normal", "options_message" };
     private static readonly uint[] _optionsMessageFieldTags = new uint[] { 26, 10, 18 };
     public static OptionsMessage DefaultInstance {
@@ -68,7 +69,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     }
     
     public override OptionsMessage DefaultInstanceForType {
-      get { return defaultInstance; }
+      get { return DefaultInstance; }
     }
     
     protected override OptionsMessage ThisMessage {
@@ -186,11 +187,15 @@ namespace Google.ProtocolBuffers.TestProtos {
     public static OptionsMessage ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
       return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
     }
+    private OptionsMessage 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(OptionsMessage prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -200,21 +205,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(OptionsMessage cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
+      
+      private bool resultIsReadOnly;
+      private OptionsMessage result;
+      
+      private OptionsMessage PrepareBuilder() {
+        if (resultIsReadOnly) {
+          OptionsMessage original = result;
+          result = new OptionsMessage();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
       
-      OptionsMessage result = new OptionsMessage();
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override OptionsMessage MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new OptionsMessage();
+        result = DefaultInstance;
+        resultIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -226,12 +258,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override OptionsMessage BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (resultIsReadOnly) {
+          return result;
         }
-        OptionsMessage returnMe = result;
-        result = null;
-        return returnMe;
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -245,6 +276,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(OptionsMessage other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.OptionsMessage.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasNormal) {
           Normal = other.Normal;
         }
@@ -263,6 +295,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -327,11 +360,13 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetNormal(string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasNormal = true;
         result.normal_ = value;
         return this;
       }
       public Builder ClearNormal() {
+        PrepareBuilder();
         result.hasNormal = false;
         result.normal_ = "";
         return this;
@@ -346,11 +381,13 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetOptionsMessage_(string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasOptionsMessage_ = true;
         result.optionsMessage_ = value;
         return this;
       }
       public Builder ClearOptionsMessage_() {
+        PrepareBuilder();
         result.hasOptionsMessage_ = false;
         result.optionsMessage_ = "";
         return this;
@@ -365,11 +402,13 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetCustomName(string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasCustomName = true;
         result.customized_ = value;
         return this;
       }
       public Builder ClearCustomName() {
+        PrepareBuilder();
         result.hasCustomName = false;
         result.customized_ = "";
         return this;

Plik diff jest za duży
+ 371 - 105
src/ProtocolBuffers.Test/TestProtos/UnitTestCustomOptionsProtoFile.cs


+ 64 - 21
src/ProtocolBuffers.Test/TestProtos/UnitTestEmbedOptimizeForProtoFile.cs

@@ -1,5 +1,5 @@
 // Generated by ProtoGen, Version=2.3.0.277, Culture=neutral, PublicKeyToken=17b3b1f090c3ea48.  DO NOT EDIT!
-#pragma warning disable 1591
+#pragma warning disable 1591, 0612
 #region Designer generated code
 
 using pb = global::Google.ProtocolBuffers;
@@ -64,7 +64,8 @@ namespace Google.ProtocolBuffers.TestProtos {
   [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
   [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
   public sealed partial class TestEmbedOptimizedForSize : pb::GeneratedMessage<TestEmbedOptimizedForSize, TestEmbedOptimizedForSize.Builder> {
-    private static readonly TestEmbedOptimizedForSize defaultInstance = new Builder().BuildPartial();
+    private TestEmbedOptimizedForSize() { }
+    private static readonly TestEmbedOptimizedForSize defaultInstance = new TestEmbedOptimizedForSize().MakeReadOnly();
     private static readonly string[] _testEmbedOptimizedForSizeFieldNames = new string[] { "optional_message", "repeated_message" };
     private static readonly uint[] _testEmbedOptimizedForSizeFieldTags = new uint[] { 10, 18 };
     public static TestEmbedOptimizedForSize DefaultInstance {
@@ -72,7 +73,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     }
     
     public override TestEmbedOptimizedForSize DefaultInstanceForType {
-      get { return defaultInstance; }
+      get { return DefaultInstance; }
     }
     
     protected override TestEmbedOptimizedForSize ThisMessage {
@@ -89,12 +90,12 @@ namespace Google.ProtocolBuffers.TestProtos {
     
     public const int OptionalMessageFieldNumber = 1;
     private bool hasOptionalMessage;
-    private global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize optionalMessage_ = global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.DefaultInstance;
+    private global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize optionalMessage_;
     public bool HasOptionalMessage {
       get { return hasOptionalMessage; }
     }
     public global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize OptionalMessage {
-      get { return optionalMessage_; }
+      get { return optionalMessage_ ?? global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.DefaultInstance; }
     }
     
     public const int RepeatedMessageFieldNumber = 2;
@@ -182,11 +183,16 @@ namespace Google.ProtocolBuffers.TestProtos {
     public static TestEmbedOptimizedForSize ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
       return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
     }
+    private TestEmbedOptimizedForSize MakeReadOnly() {
+      repeatedMessage_.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(TestEmbedOptimizedForSize prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -196,21 +202,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(TestEmbedOptimizedForSize cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
+      
+      private bool resultIsReadOnly;
+      private TestEmbedOptimizedForSize result;
+      
+      private TestEmbedOptimizedForSize PrepareBuilder() {
+        if (resultIsReadOnly) {
+          TestEmbedOptimizedForSize original = result;
+          result = new TestEmbedOptimizedForSize();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
       
-      TestEmbedOptimizedForSize result = new TestEmbedOptimizedForSize();
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override TestEmbedOptimizedForSize MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new TestEmbedOptimizedForSize();
+        result = DefaultInstance;
+        resultIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -222,13 +255,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override TestEmbedOptimizedForSize BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (resultIsReadOnly) {
+          return result;
         }
-        result.repeatedMessage_.MakeReadOnly();
-        TestEmbedOptimizedForSize returnMe = result;
-        result = null;
-        return returnMe;
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -242,11 +273,12 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(TestEmbedOptimizedForSize other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.TestEmbedOptimizedForSize.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasOptionalMessage) {
           MergeOptionalMessage(other.OptionalMessage);
         }
         if (other.repeatedMessage_.Count != 0) {
-          base.AddRange(other.repeatedMessage_, result.repeatedMessage_);
+          result.repeatedMessage_.Add(other.repeatedMessage_);
         }
         this.MergeUnknownFields(other.UnknownFields);
         return this;
@@ -257,6 +289,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -322,18 +355,21 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetOptionalMessage(global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasOptionalMessage = true;
         result.optionalMessage_ = value;
         return this;
       }
       public Builder SetOptionalMessage(global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.hasOptionalMessage = true;
         result.optionalMessage_ = builderForValue.Build();
         return this;
       }
       public Builder MergeOptionalMessage(global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         if (result.hasOptionalMessage &&
             result.optionalMessage_ != global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.DefaultInstance) {
             result.optionalMessage_ = global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.CreateBuilder(result.optionalMessage_).MergeFrom(value).BuildPartial();
@@ -344,13 +380,14 @@ namespace Google.ProtocolBuffers.TestProtos {
         return this;
       }
       public Builder ClearOptionalMessage() {
+        PrepareBuilder();
         result.hasOptionalMessage = false;
-        result.optionalMessage_ = global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.DefaultInstance;
+        result.optionalMessage_ = null;
         return this;
       }
       
       public pbc::IPopsicleList<global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize> RepeatedMessageList {
-        get { return result.repeatedMessage_; }
+        get { return PrepareBuilder().repeatedMessage_; }
       }
       public int RepeatedMessageCount {
         get { return result.RepeatedMessageCount; }
@@ -360,29 +397,35 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetRepeatedMessage(int index, global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.repeatedMessage_[index] = value;
         return this;
       }
       public Builder SetRepeatedMessage(int index, global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.repeatedMessage_[index] = builderForValue.Build();
         return this;
       }
       public Builder AddRepeatedMessage(global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.repeatedMessage_.Add(value);
         return this;
       }
       public Builder AddRepeatedMessage(global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.repeatedMessage_.Add(builderForValue.Build());
         return this;
       }
       public Builder AddRangeRepeatedMessage(scg::IEnumerable<global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize> values) {
-        base.AddRange(values, result.repeatedMessage_);
+        PrepareBuilder();
+        result.repeatedMessage_.Add(values);
         return this;
       }
       public Builder ClearRepeatedMessage() {
+        PrepareBuilder();
         result.repeatedMessage_.Clear();
         return this;
       }

+ 1 - 1
src/ProtocolBuffers.Test/TestProtos/UnitTestEmptyProtoFile.cs

@@ -1,5 +1,5 @@
 // Generated by ProtoGen, Version=2.3.0.277, Culture=neutral, PublicKeyToken=17b3b1f090c3ea48.  DO NOT EDIT!
-#pragma warning disable 1591
+#pragma warning disable 1591, 0612
 #region Designer generated code
 
 using pb = global::Google.ProtocolBuffers;

+ 2174 - 56
src/ProtocolBuffers.Test/TestProtos/UnitTestExtrasIssuesProtoFile.cs

@@ -1,5 +1,5 @@
 // Generated by ProtoGen, Version=2.3.0.277, Culture=neutral, PublicKeyToken=17b3b1f090c3ea48.  DO NOT EDIT!
-#pragma warning disable 1591
+#pragma warning disable 1591, 0612
 #region Designer generated code
 
 using pb = global::Google.ProtocolBuffers;
@@ -26,6 +26,16 @@ namespace UnitTest.Issues.TestProtos {
     internal static pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.AB, global::UnitTest.Issues.TestProtos.AB.Builder> internal__static_unittest_issues_AB__FieldAccessorTable;
     internal static pbd::MessageDescriptor internal__static_unittest_issues_NumberField__Descriptor;
     internal static pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.NumberField, global::UnitTest.Issues.TestProtos.NumberField.Builder> internal__static_unittest_issues_NumberField__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_unittest_issues_MyMessageAReferenceB__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.MyMessageAReferenceB, global::UnitTest.Issues.TestProtos.MyMessageAReferenceB.Builder> internal__static_unittest_issues_MyMessageAReferenceB__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_unittest_issues_MyMessageBReferenceA__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.MyMessageBReferenceA, global::UnitTest.Issues.TestProtos.MyMessageBReferenceA.Builder> internal__static_unittest_issues_MyMessageBReferenceA__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_unittest_issues_NegativeEnumMessage__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.NegativeEnumMessage, global::UnitTest.Issues.TestProtos.NegativeEnumMessage.Builder> internal__static_unittest_issues_NegativeEnumMessage__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_unittest_issues_DeprecatedChild__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.DeprecatedChild, global::UnitTest.Issues.TestProtos.DeprecatedChild.Builder> internal__static_unittest_issues_DeprecatedChild__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_unittest_issues_DeprecatedFieldsMessage__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage, global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage.Builder> internal__static_unittest_issues_DeprecatedFieldsMessage__FieldAccessorTable;
     #endregion
     #region Descriptor
     public static pbd::FileDescriptor Descriptor {
@@ -38,9 +48,26 @@ namespace UnitTest.Issues.TestProtos {
           "ChxleHRlc3QvdW5pdHRlc3RfaXNzdWVzLnByb3RvEg91bml0dGVzdF9pc3N1" + 
           "ZXMaJGdvb2dsZS9wcm90b2J1Zi9jc2hhcnBfb3B0aW9ucy5wcm90byIPCgFB" + 
           "EgoKAl9BGAEgASgFIg8KAUISCgoCQl8YASABKAUiEQoCQUISCwoDYV9iGAEg" + 
-          "ASgFIhoKC051bWJlckZpZWxkEgsKA18wMRgBIAEoBUJASAHCPjsKGlVuaXRU" + 
-          "ZXN0Lklzc3Vlcy5UZXN0UHJvdG9zEh1Vbml0VGVzdEV4dHJhc0lzc3Vlc1By" + 
-          "b3RvRmlsZQ==");
+          "ASgFIhoKC051bWJlckZpZWxkEgsKA18wMRgBIAEoBSJMChRNeU1lc3NhZ2VB" + 
+          "UmVmZXJlbmNlQhI0CgV2YWx1ZRgBIAIoCzIlLnVuaXR0ZXN0X2lzc3Vlcy5N" + 
+          "eU1lc3NhZ2VCUmVmZXJlbmNlQSJMChRNeU1lc3NhZ2VCUmVmZXJlbmNlQRI0" + 
+          "CgV2YWx1ZRgBIAIoCzIlLnVuaXR0ZXN0X2lzc3Vlcy5NeU1lc3NhZ2VBUmVm" + 
+          "ZXJlbmNlQiKsAQoTTmVnYXRpdmVFbnVtTWVzc2FnZRIsCgV2YWx1ZRgBIAEo" + 
+          "DjIdLnVuaXR0ZXN0X2lzc3Vlcy5OZWdhdGl2ZUVudW0SLQoGdmFsdWVzGAIg" + 
+          "AygOMh0udW5pdHRlc3RfaXNzdWVzLk5lZ2F0aXZlRW51bRI4Cg1wYWNrZWRf" + 
+          "dmFsdWVzGAMgAygOMh0udW5pdHRlc3RfaXNzdWVzLk5lZ2F0aXZlRW51bUIC" + 
+          "EAEiEQoPRGVwcmVjYXRlZENoaWxkIrkCChdEZXByZWNhdGVkRmllbGRzTWVz" + 
+          "c2FnZRIaCg5QcmltaXRpdmVWYWx1ZRgBIAEoBUICGAESGgoOUHJpbWl0aXZl" + 
+          "QXJyYXkYAiADKAVCAhgBEjoKDE1lc3NhZ2VWYWx1ZRgDIAEoCzIgLnVuaXR0" + 
+          "ZXN0X2lzc3Vlcy5EZXByZWNhdGVkQ2hpbGRCAhgBEjoKDE1lc3NhZ2VBcnJh" + 
+          "eRgEIAMoCzIgLnVuaXR0ZXN0X2lzc3Vlcy5EZXByZWNhdGVkQ2hpbGRCAhgB" + 
+          "EjYKCUVudW1WYWx1ZRgFIAEoDjIfLnVuaXR0ZXN0X2lzc3Vlcy5EZXByZWNh" + 
+          "dGVkRW51bUICGAESNgoJRW51bUFycmF5GAYgAygOMh8udW5pdHRlc3RfaXNz" + 
+          "dWVzLkRlcHJlY2F0ZWRFbnVtQgIYASpHCgxOZWdhdGl2ZUVudW0SFgoJRml2" + 
+          "ZUJlbG93EPv//////////wESFQoITWludXNPbmUQ////////////ARIICgRa" + 
+          "ZXJvEAAqGQoORGVwcmVjYXRlZEVudW0SBwoDb25lEAFCQEgBwj47ChpVbml0" + 
+          "VGVzdC5Jc3N1ZXMuVGVzdFByb3RvcxIdVW5pdFRlc3RFeHRyYXNJc3N1ZXNQ" + 
+          "cm90b0ZpbGU=");
       pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {
         descriptor = root;
         internal__static_unittest_issues_A__Descriptor = Descriptor.MessageTypes[0];
@@ -59,6 +86,26 @@ namespace UnitTest.Issues.TestProtos {
         internal__static_unittest_issues_NumberField__FieldAccessorTable = 
             new pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.NumberField, global::UnitTest.Issues.TestProtos.NumberField.Builder>(internal__static_unittest_issues_NumberField__Descriptor,
                 new string[] { "_01", });
+        internal__static_unittest_issues_MyMessageAReferenceB__Descriptor = Descriptor.MessageTypes[4];
+        internal__static_unittest_issues_MyMessageAReferenceB__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.MyMessageAReferenceB, global::UnitTest.Issues.TestProtos.MyMessageAReferenceB.Builder>(internal__static_unittest_issues_MyMessageAReferenceB__Descriptor,
+                new string[] { "Value", });
+        internal__static_unittest_issues_MyMessageBReferenceA__Descriptor = Descriptor.MessageTypes[5];
+        internal__static_unittest_issues_MyMessageBReferenceA__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.MyMessageBReferenceA, global::UnitTest.Issues.TestProtos.MyMessageBReferenceA.Builder>(internal__static_unittest_issues_MyMessageBReferenceA__Descriptor,
+                new string[] { "Value", });
+        internal__static_unittest_issues_NegativeEnumMessage__Descriptor = Descriptor.MessageTypes[6];
+        internal__static_unittest_issues_NegativeEnumMessage__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.NegativeEnumMessage, global::UnitTest.Issues.TestProtos.NegativeEnumMessage.Builder>(internal__static_unittest_issues_NegativeEnumMessage__Descriptor,
+                new string[] { "Value", "Values", "PackedValues", });
+        internal__static_unittest_issues_DeprecatedChild__Descriptor = Descriptor.MessageTypes[7];
+        internal__static_unittest_issues_DeprecatedChild__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.DeprecatedChild, global::UnitTest.Issues.TestProtos.DeprecatedChild.Builder>(internal__static_unittest_issues_DeprecatedChild__Descriptor,
+                new string[] { });
+        internal__static_unittest_issues_DeprecatedFieldsMessage__Descriptor = Descriptor.MessageTypes[8];
+        internal__static_unittest_issues_DeprecatedFieldsMessage__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage, global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage.Builder>(internal__static_unittest_issues_DeprecatedFieldsMessage__Descriptor,
+                new string[] { "PrimitiveValue", "PrimitiveArray", "MessageValue", "MessageArray", "EnumValue", "EnumArray", });
         pb::ExtensionRegistry registry = pb::ExtensionRegistry.CreateInstance();
         RegisterAllExtensions(registry);
         global::Google.ProtocolBuffers.DescriptorProtos.CSharpOptions.RegisterAllExtensions(registry);
@@ -72,12 +119,30 @@ namespace UnitTest.Issues.TestProtos {
     #endregion
     
   }
+  #region Enums
+  [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+  [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
+  public enum NegativeEnum {
+    FiveBelow = -5,
+    MinusOne = -1,
+    Zero = 0,
+  }
+  
+  [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+  [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
+  public enum DeprecatedEnum {
+    one = 1,
+  }
+  
+  #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 A : pb::GeneratedMessage<A, A.Builder> {
-    private static readonly A defaultInstance = new Builder().BuildPartial();
+    private A() { }
+    private static readonly A defaultInstance = new A().MakeReadOnly();
     private static readonly string[] _aFieldNames = new string[] { "_A" };
     private static readonly uint[] _aFieldTags = new uint[] { 8 };
     public static A DefaultInstance {
@@ -85,7 +150,7 @@ namespace UnitTest.Issues.TestProtos {
     }
     
     public override A DefaultInstanceForType {
-      get { return defaultInstance; }
+      get { return DefaultInstance; }
     }
     
     protected override A ThisMessage {
@@ -171,11 +236,15 @@ namespace UnitTest.Issues.TestProtos {
     public static A ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
       return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
     }
+    private A 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(A prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -185,21 +254,48 @@ namespace UnitTest.Issues.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(A cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
+      
+      private bool resultIsReadOnly;
+      private A result;
+      
+      private A PrepareBuilder() {
+        if (resultIsReadOnly) {
+          A original = result;
+          result = new A();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
       
-      A result = new A();
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override A MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new A();
+        result = DefaultInstance;
+        resultIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -211,12 +307,11 @@ namespace UnitTest.Issues.TestProtos {
       }
       
       public override A BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (resultIsReadOnly) {
+          return result;
         }
-        A returnMe = result;
-        result = null;
-        return returnMe;
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -230,6 +325,7 @@ namespace UnitTest.Issues.TestProtos {
       
       public override Builder MergeFrom(A other) {
         if (other == global::UnitTest.Issues.TestProtos.A.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasA_) {
           A_ = other.A_;
         }
@@ -242,6 +338,7 @@ namespace UnitTest.Issues.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -297,11 +394,13 @@ namespace UnitTest.Issues.TestProtos {
         set { SetA_(value); }
       }
       public Builder SetA_(int value) {
+        PrepareBuilder();
         result.hasA_ = true;
         result.a_ = value;
         return this;
       }
       public Builder ClearA_() {
+        PrepareBuilder();
         result.hasA_ = false;
         result.a_ = 0;
         return this;
@@ -316,7 +415,8 @@ namespace UnitTest.Issues.TestProtos {
   [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
   [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
   public sealed partial class B : pb::GeneratedMessage<B, B.Builder> {
-    private static readonly B defaultInstance = new Builder().BuildPartial();
+    private B() { }
+    private static readonly B defaultInstance = new B().MakeReadOnly();
     private static readonly string[] _bFieldNames = new string[] { "B_" };
     private static readonly uint[] _bFieldTags = new uint[] { 8 };
     public static B DefaultInstance {
@@ -324,7 +424,7 @@ namespace UnitTest.Issues.TestProtos {
     }
     
     public override B DefaultInstanceForType {
-      get { return defaultInstance; }
+      get { return DefaultInstance; }
     }
     
     protected override B ThisMessage {
@@ -410,11 +510,15 @@ namespace UnitTest.Issues.TestProtos {
     public static B ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
       return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
     }
+    private B 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(B prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -424,21 +528,48 @@ namespace UnitTest.Issues.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(B cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
+      
+      private bool resultIsReadOnly;
+      private B result;
+      
+      private B PrepareBuilder() {
+        if (resultIsReadOnly) {
+          B original = result;
+          result = new B();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
       
-      B result = new B();
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override B MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new B();
+        result = DefaultInstance;
+        resultIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -450,12 +581,11 @@ namespace UnitTest.Issues.TestProtos {
       }
       
       public override B BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (resultIsReadOnly) {
+          return result;
         }
-        B returnMe = result;
-        result = null;
-        return returnMe;
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -469,6 +599,7 @@ namespace UnitTest.Issues.TestProtos {
       
       public override Builder MergeFrom(B other) {
         if (other == global::UnitTest.Issues.TestProtos.B.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasB_) {
           B_ = other.B_;
         }
@@ -481,6 +612,7 @@ namespace UnitTest.Issues.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -536,11 +668,13 @@ namespace UnitTest.Issues.TestProtos {
         set { SetB_(value); }
       }
       public Builder SetB_(int value) {
+        PrepareBuilder();
         result.hasB_ = true;
         result.b_ = value;
         return this;
       }
       public Builder ClearB_() {
+        PrepareBuilder();
         result.hasB_ = false;
         result.b_ = 0;
         return this;
@@ -555,7 +689,8 @@ namespace UnitTest.Issues.TestProtos {
   [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
   [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
   public sealed partial class AB : pb::GeneratedMessage<AB, AB.Builder> {
-    private static readonly AB defaultInstance = new Builder().BuildPartial();
+    private AB() { }
+    private static readonly AB defaultInstance = new AB().MakeReadOnly();
     private static readonly string[] _aBFieldNames = new string[] { "a_b" };
     private static readonly uint[] _aBFieldTags = new uint[] { 8 };
     public static AB DefaultInstance {
@@ -563,7 +698,7 @@ namespace UnitTest.Issues.TestProtos {
     }
     
     public override AB DefaultInstanceForType {
-      get { return defaultInstance; }
+      get { return DefaultInstance; }
     }
     
     protected override AB ThisMessage {
@@ -649,11 +784,15 @@ namespace UnitTest.Issues.TestProtos {
     public static AB ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
       return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
     }
+    private AB 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(AB prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -663,21 +802,48 @@ namespace UnitTest.Issues.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(AB cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
+      
+      private bool resultIsReadOnly;
+      private AB result;
+      
+      private AB PrepareBuilder() {
+        if (resultIsReadOnly) {
+          AB original = result;
+          result = new AB();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
       
-      AB result = new AB();
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override AB MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new AB();
+        result = DefaultInstance;
+        resultIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -689,12 +855,11 @@ namespace UnitTest.Issues.TestProtos {
       }
       
       public override AB BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (resultIsReadOnly) {
+          return result;
         }
-        AB returnMe = result;
-        result = null;
-        return returnMe;
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -708,6 +873,7 @@ namespace UnitTest.Issues.TestProtos {
       
       public override Builder MergeFrom(AB other) {
         if (other == global::UnitTest.Issues.TestProtos.AB.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasAB_) {
           AB_ = other.AB_;
         }
@@ -720,6 +886,7 @@ namespace UnitTest.Issues.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -775,11 +942,13 @@ namespace UnitTest.Issues.TestProtos {
         set { SetAB_(value); }
       }
       public Builder SetAB_(int value) {
+        PrepareBuilder();
         result.hasAB_ = true;
         result.aB_ = value;
         return this;
       }
       public Builder ClearAB_() {
+        PrepareBuilder();
         result.hasAB_ = false;
         result.aB_ = 0;
         return this;
@@ -794,7 +963,8 @@ namespace UnitTest.Issues.TestProtos {
   [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
   [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
   public sealed partial class NumberField : pb::GeneratedMessage<NumberField, NumberField.Builder> {
-    private static readonly NumberField defaultInstance = new Builder().BuildPartial();
+    private NumberField() { }
+    private static readonly NumberField defaultInstance = new NumberField().MakeReadOnly();
     private static readonly string[] _numberFieldFieldNames = new string[] { "_01" };
     private static readonly uint[] _numberFieldFieldTags = new uint[] { 8 };
     public static NumberField DefaultInstance {
@@ -802,7 +972,7 @@ namespace UnitTest.Issues.TestProtos {
     }
     
     public override NumberField DefaultInstanceForType {
-      get { return defaultInstance; }
+      get { return DefaultInstance; }
     }
     
     protected override NumberField ThisMessage {
@@ -890,11 +1060,15 @@ namespace UnitTest.Issues.TestProtos {
     public static NumberField ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
       return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
     }
+    private NumberField 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(NumberField prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -904,21 +1078,48 @@ namespace UnitTest.Issues.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(NumberField cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
+      
+      private bool resultIsReadOnly;
+      private NumberField result;
+      
+      private NumberField PrepareBuilder() {
+        if (resultIsReadOnly) {
+          NumberField original = result;
+          result = new NumberField();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
       
-      NumberField result = new NumberField();
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override NumberField MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new NumberField();
+        result = DefaultInstance;
+        resultIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -930,12 +1131,11 @@ namespace UnitTest.Issues.TestProtos {
       }
       
       public override NumberField BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (resultIsReadOnly) {
+          return result;
         }
-        NumberField returnMe = result;
-        result = null;
-        return returnMe;
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -949,6 +1149,7 @@ namespace UnitTest.Issues.TestProtos {
       
       public override Builder MergeFrom(NumberField other) {
         if (other == global::UnitTest.Issues.TestProtos.NumberField.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.Has_01) {
           _01 = other._01;
         }
@@ -961,6 +1162,7 @@ namespace UnitTest.Issues.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -1018,11 +1220,13 @@ namespace UnitTest.Issues.TestProtos {
       }
       [global::System.CLSCompliant(false)]
       public Builder Set_01(int value) {
+        PrepareBuilder();
         result.has_01 = true;
         result._01_ = value;
         return this;
       }
       public Builder Clear_01() {
+        PrepareBuilder();
         result.has_01 = false;
         result._01_ = 0;
         return this;
@@ -1033,6 +1237,1920 @@ namespace UnitTest.Issues.TestProtos {
     }
   }
   
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+  [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
+  public sealed partial class MyMessageAReferenceB : pb::GeneratedMessage<MyMessageAReferenceB, MyMessageAReferenceB.Builder> {
+    private MyMessageAReferenceB() { }
+    private static readonly MyMessageAReferenceB defaultInstance = new MyMessageAReferenceB().MakeReadOnly();
+    private static readonly string[] _myMessageAReferenceBFieldNames = new string[] { "value" };
+    private static readonly uint[] _myMessageAReferenceBFieldTags = new uint[] { 10 };
+    public static MyMessageAReferenceB DefaultInstance {
+      get { return defaultInstance; }
+    }
+    
+    public override MyMessageAReferenceB DefaultInstanceForType {
+      get { return DefaultInstance; }
+    }
+    
+    protected override MyMessageAReferenceB ThisMessage {
+      get { return this; }
+    }
+    
+    public static pbd::MessageDescriptor Descriptor {
+      get { return global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.internal__static_unittest_issues_MyMessageAReferenceB__Descriptor; }
+    }
+    
+    protected override pb::FieldAccess.FieldAccessorTable<MyMessageAReferenceB, MyMessageAReferenceB.Builder> InternalFieldAccessors {
+      get { return global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.internal__static_unittest_issues_MyMessageAReferenceB__FieldAccessorTable; }
+    }
+    
+    public const int ValueFieldNumber = 1;
+    private bool hasValue;
+    private global::UnitTest.Issues.TestProtos.MyMessageBReferenceA value_;
+    public bool HasValue {
+      get { return hasValue; }
+    }
+    public global::UnitTest.Issues.TestProtos.MyMessageBReferenceA Value {
+      get { return value_ ?? global::UnitTest.Issues.TestProtos.MyMessageBReferenceA.DefaultInstance; }
+    }
+    
+    public override bool IsInitialized {
+      get {
+        if (!hasValue) return false;
+        if (!Value.IsInitialized) return false;
+        return true;
+      }
+    }
+    
+    public override void WriteTo(pb::ICodedOutputStream output) {
+      int size = SerializedSize;
+      string[] field_names = _myMessageAReferenceBFieldNames;
+      if (hasValue) {
+        output.WriteMessage(1, field_names[0], Value);
+      }
+      UnknownFields.WriteTo(output);
+    }
+    
+    private int memoizedSerializedSize = -1;
+    public override int SerializedSize {
+      get {
+        int size = memoizedSerializedSize;
+        if (size != -1) return size;
+        
+        size = 0;
+        if (hasValue) {
+          size += pb::CodedOutputStream.ComputeMessageSize(1, Value);
+        }
+        size += UnknownFields.SerializedSize;
+        memoizedSerializedSize = size;
+        return size;
+      }
+    }
+    
+    public static MyMessageAReferenceB ParseFrom(pb::ByteString data) {
+      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+    }
+    public static MyMessageAReferenceB ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
+      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+    }
+    public static MyMessageAReferenceB ParseFrom(byte[] data) {
+      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+    }
+    public static MyMessageAReferenceB ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
+      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+    }
+    public static MyMessageAReferenceB ParseFrom(global::System.IO.Stream input) {
+      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+    }
+    public static MyMessageAReferenceB ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
+      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+    }
+    public static MyMessageAReferenceB ParseDelimitedFrom(global::System.IO.Stream input) {
+      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
+    }
+    public static MyMessageAReferenceB ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
+      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
+    }
+    public static MyMessageAReferenceB ParseFrom(pb::ICodedInputStream input) {
+      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+    }
+    public static MyMessageAReferenceB ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+    }
+    private MyMessageAReferenceB 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(MyMessageAReferenceB 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::GeneratedBuilder<MyMessageAReferenceB, Builder> {
+      protected override Builder ThisBuilder {
+        get { return this; }
+      }
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(MyMessageAReferenceB cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
+      
+      private bool resultIsReadOnly;
+      private MyMessageAReferenceB result;
+      
+      private MyMessageAReferenceB PrepareBuilder() {
+        if (resultIsReadOnly) {
+          MyMessageAReferenceB original = result;
+          result = new MyMessageAReferenceB();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
+      
+      protected override MyMessageAReferenceB MessageBeingBuilt {
+        get { return PrepareBuilder(); }
+      }
+      
+      public override Builder Clear() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+        return this;
+      }
+      
+      public override Builder Clone() {
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
+      }
+      
+      public override pbd::MessageDescriptor DescriptorForType {
+        get { return global::UnitTest.Issues.TestProtos.MyMessageAReferenceB.Descriptor; }
+      }
+      
+      public override MyMessageAReferenceB DefaultInstanceForType {
+        get { return global::UnitTest.Issues.TestProtos.MyMessageAReferenceB.DefaultInstance; }
+      }
+      
+      public override MyMessageAReferenceB BuildPartial() {
+        if (resultIsReadOnly) {
+          return result;
+        }
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
+      }
+      
+      public override Builder MergeFrom(pb::IMessage other) {
+        if (other is MyMessageAReferenceB) {
+          return MergeFrom((MyMessageAReferenceB) other);
+        } else {
+          base.MergeFrom(other);
+          return this;
+        }
+      }
+      
+      public override Builder MergeFrom(MyMessageAReferenceB other) {
+        if (other == global::UnitTest.Issues.TestProtos.MyMessageAReferenceB.DefaultInstance) return this;
+        PrepareBuilder();
+        if (other.HasValue) {
+          MergeValue(other.Value);
+        }
+        this.MergeUnknownFields(other.UnknownFields);
+        return this;
+      }
+      
+      public override Builder MergeFrom(pb::ICodedInputStream input) {
+        return MergeFrom(input, pb::ExtensionRegistry.Empty);
+      }
+      
+      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
+        pb::UnknownFieldSet.Builder unknownFields = null;
+        uint tag;
+        string field_name;
+        while (input.ReadTag(out tag, out field_name)) {
+          if(tag == 0 && field_name != null) {
+            int field_ordinal = global::System.Array.BinarySearch(_myMessageAReferenceBFieldNames, field_name, global::System.StringComparer.Ordinal);
+            if(field_ordinal >= 0)
+              tag = _myMessageAReferenceBFieldTags[field_ordinal];
+            else {
+              if (unknownFields == null) {
+                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+              }
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+              continue;
+            }
+          }
+          switch (tag) {
+            case 0: {
+              throw pb::InvalidProtocolBufferException.InvalidTag();
+            }
+            default: {
+              if (pb::WireFormat.IsEndGroupTag(tag)) {
+                if (unknownFields != null) {
+                  this.UnknownFields = unknownFields.Build();
+                }
+                return this;
+              }
+              if (unknownFields == null) {
+                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+              }
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+              break;
+            }
+            case 10: {
+              global::UnitTest.Issues.TestProtos.MyMessageBReferenceA.Builder subBuilder = global::UnitTest.Issues.TestProtos.MyMessageBReferenceA.CreateBuilder();
+              if (result.hasValue) {
+                subBuilder.MergeFrom(Value);
+              }
+              input.ReadMessage(subBuilder, extensionRegistry);
+              Value = subBuilder.BuildPartial();
+              break;
+            }
+          }
+        }
+        
+        if (unknownFields != null) {
+          this.UnknownFields = unknownFields.Build();
+        }
+        return this;
+      }
+      
+      
+      public bool HasValue {
+       get { return result.hasValue; }
+      }
+      public global::UnitTest.Issues.TestProtos.MyMessageBReferenceA Value {
+        get { return result.Value; }
+        set { SetValue(value); }
+      }
+      public Builder SetValue(global::UnitTest.Issues.TestProtos.MyMessageBReferenceA value) {
+        pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
+        result.hasValue = true;
+        result.value_ = value;
+        return this;
+      }
+      public Builder SetValue(global::UnitTest.Issues.TestProtos.MyMessageBReferenceA.Builder builderForValue) {
+        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
+        result.hasValue = true;
+        result.value_ = builderForValue.Build();
+        return this;
+      }
+      public Builder MergeValue(global::UnitTest.Issues.TestProtos.MyMessageBReferenceA value) {
+        pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
+        if (result.hasValue &&
+            result.value_ != global::UnitTest.Issues.TestProtos.MyMessageBReferenceA.DefaultInstance) {
+            result.value_ = global::UnitTest.Issues.TestProtos.MyMessageBReferenceA.CreateBuilder(result.value_).MergeFrom(value).BuildPartial();
+        } else {
+          result.value_ = value;
+        }
+        result.hasValue = true;
+        return this;
+      }
+      public Builder ClearValue() {
+        PrepareBuilder();
+        result.hasValue = false;
+        result.value_ = null;
+        return this;
+      }
+    }
+    static MyMessageAReferenceB() {
+      object.ReferenceEquals(global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.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 MyMessageBReferenceA : pb::GeneratedMessage<MyMessageBReferenceA, MyMessageBReferenceA.Builder> {
+    private MyMessageBReferenceA() { }
+    private static readonly MyMessageBReferenceA defaultInstance = new MyMessageBReferenceA().MakeReadOnly();
+    private static readonly string[] _myMessageBReferenceAFieldNames = new string[] { "value" };
+    private static readonly uint[] _myMessageBReferenceAFieldTags = new uint[] { 10 };
+    public static MyMessageBReferenceA DefaultInstance {
+      get { return defaultInstance; }
+    }
+    
+    public override MyMessageBReferenceA DefaultInstanceForType {
+      get { return DefaultInstance; }
+    }
+    
+    protected override MyMessageBReferenceA ThisMessage {
+      get { return this; }
+    }
+    
+    public static pbd::MessageDescriptor Descriptor {
+      get { return global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.internal__static_unittest_issues_MyMessageBReferenceA__Descriptor; }
+    }
+    
+    protected override pb::FieldAccess.FieldAccessorTable<MyMessageBReferenceA, MyMessageBReferenceA.Builder> InternalFieldAccessors {
+      get { return global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.internal__static_unittest_issues_MyMessageBReferenceA__FieldAccessorTable; }
+    }
+    
+    public const int ValueFieldNumber = 1;
+    private bool hasValue;
+    private global::UnitTest.Issues.TestProtos.MyMessageAReferenceB value_;
+    public bool HasValue {
+      get { return hasValue; }
+    }
+    public global::UnitTest.Issues.TestProtos.MyMessageAReferenceB Value {
+      get { return value_ ?? global::UnitTest.Issues.TestProtos.MyMessageAReferenceB.DefaultInstance; }
+    }
+    
+    public override bool IsInitialized {
+      get {
+        if (!hasValue) return false;
+        if (!Value.IsInitialized) return false;
+        return true;
+      }
+    }
+    
+    public override void WriteTo(pb::ICodedOutputStream output) {
+      int size = SerializedSize;
+      string[] field_names = _myMessageBReferenceAFieldNames;
+      if (hasValue) {
+        output.WriteMessage(1, field_names[0], Value);
+      }
+      UnknownFields.WriteTo(output);
+    }
+    
+    private int memoizedSerializedSize = -1;
+    public override int SerializedSize {
+      get {
+        int size = memoizedSerializedSize;
+        if (size != -1) return size;
+        
+        size = 0;
+        if (hasValue) {
+          size += pb::CodedOutputStream.ComputeMessageSize(1, Value);
+        }
+        size += UnknownFields.SerializedSize;
+        memoizedSerializedSize = size;
+        return size;
+      }
+    }
+    
+    public static MyMessageBReferenceA ParseFrom(pb::ByteString data) {
+      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+    }
+    public static MyMessageBReferenceA ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
+      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+    }
+    public static MyMessageBReferenceA ParseFrom(byte[] data) {
+      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+    }
+    public static MyMessageBReferenceA ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
+      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+    }
+    public static MyMessageBReferenceA ParseFrom(global::System.IO.Stream input) {
+      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+    }
+    public static MyMessageBReferenceA ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
+      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+    }
+    public static MyMessageBReferenceA ParseDelimitedFrom(global::System.IO.Stream input) {
+      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
+    }
+    public static MyMessageBReferenceA ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
+      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
+    }
+    public static MyMessageBReferenceA ParseFrom(pb::ICodedInputStream input) {
+      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+    }
+    public static MyMessageBReferenceA ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+    }
+    private MyMessageBReferenceA 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(MyMessageBReferenceA 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::GeneratedBuilder<MyMessageBReferenceA, Builder> {
+      protected override Builder ThisBuilder {
+        get { return this; }
+      }
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(MyMessageBReferenceA cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
+      
+      private bool resultIsReadOnly;
+      private MyMessageBReferenceA result;
+      
+      private MyMessageBReferenceA PrepareBuilder() {
+        if (resultIsReadOnly) {
+          MyMessageBReferenceA original = result;
+          result = new MyMessageBReferenceA();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
+      
+      protected override MyMessageBReferenceA MessageBeingBuilt {
+        get { return PrepareBuilder(); }
+      }
+      
+      public override Builder Clear() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+        return this;
+      }
+      
+      public override Builder Clone() {
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
+      }
+      
+      public override pbd::MessageDescriptor DescriptorForType {
+        get { return global::UnitTest.Issues.TestProtos.MyMessageBReferenceA.Descriptor; }
+      }
+      
+      public override MyMessageBReferenceA DefaultInstanceForType {
+        get { return global::UnitTest.Issues.TestProtos.MyMessageBReferenceA.DefaultInstance; }
+      }
+      
+      public override MyMessageBReferenceA BuildPartial() {
+        if (resultIsReadOnly) {
+          return result;
+        }
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
+      }
+      
+      public override Builder MergeFrom(pb::IMessage other) {
+        if (other is MyMessageBReferenceA) {
+          return MergeFrom((MyMessageBReferenceA) other);
+        } else {
+          base.MergeFrom(other);
+          return this;
+        }
+      }
+      
+      public override Builder MergeFrom(MyMessageBReferenceA other) {
+        if (other == global::UnitTest.Issues.TestProtos.MyMessageBReferenceA.DefaultInstance) return this;
+        PrepareBuilder();
+        if (other.HasValue) {
+          MergeValue(other.Value);
+        }
+        this.MergeUnknownFields(other.UnknownFields);
+        return this;
+      }
+      
+      public override Builder MergeFrom(pb::ICodedInputStream input) {
+        return MergeFrom(input, pb::ExtensionRegistry.Empty);
+      }
+      
+      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
+        pb::UnknownFieldSet.Builder unknownFields = null;
+        uint tag;
+        string field_name;
+        while (input.ReadTag(out tag, out field_name)) {
+          if(tag == 0 && field_name != null) {
+            int field_ordinal = global::System.Array.BinarySearch(_myMessageBReferenceAFieldNames, field_name, global::System.StringComparer.Ordinal);
+            if(field_ordinal >= 0)
+              tag = _myMessageBReferenceAFieldTags[field_ordinal];
+            else {
+              if (unknownFields == null) {
+                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+              }
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+              continue;
+            }
+          }
+          switch (tag) {
+            case 0: {
+              throw pb::InvalidProtocolBufferException.InvalidTag();
+            }
+            default: {
+              if (pb::WireFormat.IsEndGroupTag(tag)) {
+                if (unknownFields != null) {
+                  this.UnknownFields = unknownFields.Build();
+                }
+                return this;
+              }
+              if (unknownFields == null) {
+                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+              }
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+              break;
+            }
+            case 10: {
+              global::UnitTest.Issues.TestProtos.MyMessageAReferenceB.Builder subBuilder = global::UnitTest.Issues.TestProtos.MyMessageAReferenceB.CreateBuilder();
+              if (result.hasValue) {
+                subBuilder.MergeFrom(Value);
+              }
+              input.ReadMessage(subBuilder, extensionRegistry);
+              Value = subBuilder.BuildPartial();
+              break;
+            }
+          }
+        }
+        
+        if (unknownFields != null) {
+          this.UnknownFields = unknownFields.Build();
+        }
+        return this;
+      }
+      
+      
+      public bool HasValue {
+       get { return result.hasValue; }
+      }
+      public global::UnitTest.Issues.TestProtos.MyMessageAReferenceB Value {
+        get { return result.Value; }
+        set { SetValue(value); }
+      }
+      public Builder SetValue(global::UnitTest.Issues.TestProtos.MyMessageAReferenceB value) {
+        pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
+        result.hasValue = true;
+        result.value_ = value;
+        return this;
+      }
+      public Builder SetValue(global::UnitTest.Issues.TestProtos.MyMessageAReferenceB.Builder builderForValue) {
+        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
+        result.hasValue = true;
+        result.value_ = builderForValue.Build();
+        return this;
+      }
+      public Builder MergeValue(global::UnitTest.Issues.TestProtos.MyMessageAReferenceB value) {
+        pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
+        if (result.hasValue &&
+            result.value_ != global::UnitTest.Issues.TestProtos.MyMessageAReferenceB.DefaultInstance) {
+            result.value_ = global::UnitTest.Issues.TestProtos.MyMessageAReferenceB.CreateBuilder(result.value_).MergeFrom(value).BuildPartial();
+        } else {
+          result.value_ = value;
+        }
+        result.hasValue = true;
+        return this;
+      }
+      public Builder ClearValue() {
+        PrepareBuilder();
+        result.hasValue = false;
+        result.value_ = null;
+        return this;
+      }
+    }
+    static MyMessageBReferenceA() {
+      object.ReferenceEquals(global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.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 NegativeEnumMessage : pb::GeneratedMessage<NegativeEnumMessage, NegativeEnumMessage.Builder> {
+    private NegativeEnumMessage() { }
+    private static readonly NegativeEnumMessage defaultInstance = new NegativeEnumMessage().MakeReadOnly();
+    private static readonly string[] _negativeEnumMessageFieldNames = new string[] { "packed_values", "value", "values" };
+    private static readonly uint[] _negativeEnumMessageFieldTags = new uint[] { 26, 8, 16 };
+    public static NegativeEnumMessage DefaultInstance {
+      get { return defaultInstance; }
+    }
+    
+    public override NegativeEnumMessage DefaultInstanceForType {
+      get { return DefaultInstance; }
+    }
+    
+    protected override NegativeEnumMessage ThisMessage {
+      get { return this; }
+    }
+    
+    public static pbd::MessageDescriptor Descriptor {
+      get { return global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.internal__static_unittest_issues_NegativeEnumMessage__Descriptor; }
+    }
+    
+    protected override pb::FieldAccess.FieldAccessorTable<NegativeEnumMessage, NegativeEnumMessage.Builder> InternalFieldAccessors {
+      get { return global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.internal__static_unittest_issues_NegativeEnumMessage__FieldAccessorTable; }
+    }
+    
+    public const int ValueFieldNumber = 1;
+    private bool hasValue;
+    private global::UnitTest.Issues.TestProtos.NegativeEnum value_ = global::UnitTest.Issues.TestProtos.NegativeEnum.FiveBelow;
+    public bool HasValue {
+      get { return hasValue; }
+    }
+    public global::UnitTest.Issues.TestProtos.NegativeEnum Value {
+      get { return value_; }
+    }
+    
+    public const int ValuesFieldNumber = 2;
+    private pbc::PopsicleList<global::UnitTest.Issues.TestProtos.NegativeEnum> values_ = new pbc::PopsicleList<global::UnitTest.Issues.TestProtos.NegativeEnum>();
+    public scg::IList<global::UnitTest.Issues.TestProtos.NegativeEnum> ValuesList {
+      get { return pbc::Lists.AsReadOnly(values_); }
+    }
+    public int ValuesCount {
+      get { return values_.Count; }
+    }
+    public global::UnitTest.Issues.TestProtos.NegativeEnum GetValues(int index) {
+      return values_[index];
+    }
+    
+    public const int PackedValuesFieldNumber = 3;
+    private int packedValuesMemoizedSerializedSize;
+    private pbc::PopsicleList<global::UnitTest.Issues.TestProtos.NegativeEnum> packedValues_ = new pbc::PopsicleList<global::UnitTest.Issues.TestProtos.NegativeEnum>();
+    public scg::IList<global::UnitTest.Issues.TestProtos.NegativeEnum> PackedValuesList {
+      get { return pbc::Lists.AsReadOnly(packedValues_); }
+    }
+    public int PackedValuesCount {
+      get { return packedValues_.Count; }
+    }
+    public global::UnitTest.Issues.TestProtos.NegativeEnum GetPackedValues(int index) {
+      return packedValues_[index];
+    }
+    
+    public override bool IsInitialized {
+      get {
+        return true;
+      }
+    }
+    
+    public override void WriteTo(pb::ICodedOutputStream output) {
+      int size = SerializedSize;
+      string[] field_names = _negativeEnumMessageFieldNames;
+      if (hasValue) {
+        output.WriteEnum(1, field_names[1], (int) Value, Value);
+      }
+      if (values_.Count > 0) {
+        output.WriteEnumArray(2, field_names[2], values_);
+      }
+      if (packedValues_.Count > 0) {
+        output.WritePackedEnumArray(3, field_names[0], packedValuesMemoizedSerializedSize, packedValues_);
+      }
+      UnknownFields.WriteTo(output);
+    }
+    
+    private int memoizedSerializedSize = -1;
+    public override int SerializedSize {
+      get {
+        int size = memoizedSerializedSize;
+        if (size != -1) return size;
+        
+        size = 0;
+        if (hasValue) {
+          size += pb::CodedOutputStream.ComputeEnumSize(1, (int) Value);
+        }
+        {
+          int dataSize = 0;
+          if (values_.Count > 0) {
+            foreach (global::UnitTest.Issues.TestProtos.NegativeEnum element in values_) {
+              dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element);
+            }
+            size += dataSize;
+            size += 1 * values_.Count;
+          }
+        }
+        {
+          int dataSize = 0;
+          if (packedValues_.Count > 0) {
+            foreach (global::UnitTest.Issues.TestProtos.NegativeEnum element in packedValues_) {
+              dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element);
+            }
+            size += dataSize;
+            size += 1;
+            size += pb::CodedOutputStream.ComputeRawVarint32Size((uint) dataSize);
+          }
+          packedValuesMemoizedSerializedSize = dataSize;
+        }
+        size += UnknownFields.SerializedSize;
+        memoizedSerializedSize = size;
+        return size;
+      }
+    }
+    
+    public static NegativeEnumMessage ParseFrom(pb::ByteString data) {
+      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+    }
+    public static NegativeEnumMessage ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
+      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+    }
+    public static NegativeEnumMessage ParseFrom(byte[] data) {
+      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+    }
+    public static NegativeEnumMessage ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
+      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+    }
+    public static NegativeEnumMessage ParseFrom(global::System.IO.Stream input) {
+      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+    }
+    public static NegativeEnumMessage ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
+      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+    }
+    public static NegativeEnumMessage ParseDelimitedFrom(global::System.IO.Stream input) {
+      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
+    }
+    public static NegativeEnumMessage ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
+      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
+    }
+    public static NegativeEnumMessage ParseFrom(pb::ICodedInputStream input) {
+      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+    }
+    public static NegativeEnumMessage ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+    }
+    private NegativeEnumMessage MakeReadOnly() {
+      values_.MakeReadOnly();
+      packedValues_.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(NegativeEnumMessage 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::GeneratedBuilder<NegativeEnumMessage, Builder> {
+      protected override Builder ThisBuilder {
+        get { return this; }
+      }
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(NegativeEnumMessage cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
+      
+      private bool resultIsReadOnly;
+      private NegativeEnumMessage result;
+      
+      private NegativeEnumMessage PrepareBuilder() {
+        if (resultIsReadOnly) {
+          NegativeEnumMessage original = result;
+          result = new NegativeEnumMessage();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
+      
+      protected override NegativeEnumMessage MessageBeingBuilt {
+        get { return PrepareBuilder(); }
+      }
+      
+      public override Builder Clear() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+        return this;
+      }
+      
+      public override Builder Clone() {
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
+      }
+      
+      public override pbd::MessageDescriptor DescriptorForType {
+        get { return global::UnitTest.Issues.TestProtos.NegativeEnumMessage.Descriptor; }
+      }
+      
+      public override NegativeEnumMessage DefaultInstanceForType {
+        get { return global::UnitTest.Issues.TestProtos.NegativeEnumMessage.DefaultInstance; }
+      }
+      
+      public override NegativeEnumMessage BuildPartial() {
+        if (resultIsReadOnly) {
+          return result;
+        }
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
+      }
+      
+      public override Builder MergeFrom(pb::IMessage other) {
+        if (other is NegativeEnumMessage) {
+          return MergeFrom((NegativeEnumMessage) other);
+        } else {
+          base.MergeFrom(other);
+          return this;
+        }
+      }
+      
+      public override Builder MergeFrom(NegativeEnumMessage other) {
+        if (other == global::UnitTest.Issues.TestProtos.NegativeEnumMessage.DefaultInstance) return this;
+        PrepareBuilder();
+        if (other.HasValue) {
+          Value = other.Value;
+        }
+        if (other.values_.Count != 0) {
+          result.values_.Add(other.values_);
+        }
+        if (other.packedValues_.Count != 0) {
+          result.packedValues_.Add(other.packedValues_);
+        }
+        this.MergeUnknownFields(other.UnknownFields);
+        return this;
+      }
+      
+      public override Builder MergeFrom(pb::ICodedInputStream input) {
+        return MergeFrom(input, pb::ExtensionRegistry.Empty);
+      }
+      
+      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
+        pb::UnknownFieldSet.Builder unknownFields = null;
+        uint tag;
+        string field_name;
+        while (input.ReadTag(out tag, out field_name)) {
+          if(tag == 0 && field_name != null) {
+            int field_ordinal = global::System.Array.BinarySearch(_negativeEnumMessageFieldNames, field_name, global::System.StringComparer.Ordinal);
+            if(field_ordinal >= 0)
+              tag = _negativeEnumMessageFieldTags[field_ordinal];
+            else {
+              if (unknownFields == null) {
+                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+              }
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+              continue;
+            }
+          }
+          switch (tag) {
+            case 0: {
+              throw pb::InvalidProtocolBufferException.InvalidTag();
+            }
+            default: {
+              if (pb::WireFormat.IsEndGroupTag(tag)) {
+                if (unknownFields != null) {
+                  this.UnknownFields = unknownFields.Build();
+                }
+                return this;
+              }
+              if (unknownFields == null) {
+                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+              }
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+              break;
+            }
+            case 8: {
+              object unknown;
+              if(input.ReadEnum(ref result.value_, out unknown)) {
+                result.hasValue = true;
+              } else if(unknown is int) {
+                if (unknownFields == null) {
+                  unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+                }
+                unknownFields.MergeVarintField(1, (ulong)(int)unknown);
+              }
+              break;
+            }
+            case 18:
+            case 16: {
+              scg::ICollection<object> unknownItems;
+              input.ReadEnumArray<global::UnitTest.Issues.TestProtos.NegativeEnum>(tag, field_name, result.values_, out unknownItems);
+              if (unknownItems != null) {
+                if (unknownFields == null) {
+                  unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+                }
+                foreach (object rawValue in unknownItems)
+                  if (rawValue is int)
+                    unknownFields.MergeVarintField(2, (ulong)(int)rawValue);
+              }
+              break;
+            }
+            case 26:
+            case 24: {
+              scg::ICollection<object> unknownItems;
+              input.ReadEnumArray<global::UnitTest.Issues.TestProtos.NegativeEnum>(tag, field_name, result.packedValues_, out unknownItems);
+              if (unknownItems != null) {
+                if (unknownFields == null) {
+                  unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+                }
+                foreach (object rawValue in unknownItems)
+                  if (rawValue is int)
+                    unknownFields.MergeVarintField(3, (ulong)(int)rawValue);
+              }
+              break;
+            }
+          }
+        }
+        
+        if (unknownFields != null) {
+          this.UnknownFields = unknownFields.Build();
+        }
+        return this;
+      }
+      
+      
+      public bool HasValue {
+       get { return result.hasValue; }
+      }
+      public global::UnitTest.Issues.TestProtos.NegativeEnum Value {
+        get { return result.Value; }
+        set { SetValue(value); }
+      }
+      public Builder SetValue(global::UnitTest.Issues.TestProtos.NegativeEnum value) {
+        PrepareBuilder();
+        result.hasValue = true;
+        result.value_ = value;
+        return this;
+      }
+      public Builder ClearValue() {
+        PrepareBuilder();
+        result.hasValue = false;
+        result.value_ = global::UnitTest.Issues.TestProtos.NegativeEnum.FiveBelow;
+        return this;
+      }
+      
+      public pbc::IPopsicleList<global::UnitTest.Issues.TestProtos.NegativeEnum> ValuesList {
+        get { return PrepareBuilder().values_; }
+      }
+      public int ValuesCount {
+        get { return result.ValuesCount; }
+      }
+      public global::UnitTest.Issues.TestProtos.NegativeEnum GetValues(int index) {
+        return result.GetValues(index);
+      }
+      public Builder SetValues(int index, global::UnitTest.Issues.TestProtos.NegativeEnum value) {
+        PrepareBuilder();
+        result.values_[index] = value;
+        return this;
+      }
+      public Builder AddValues(global::UnitTest.Issues.TestProtos.NegativeEnum value) {
+        PrepareBuilder();
+        result.values_.Add(value);
+        return this;
+      }
+      public Builder AddRangeValues(scg::IEnumerable<global::UnitTest.Issues.TestProtos.NegativeEnum> values) {
+        PrepareBuilder();
+        result.values_.Add(values);
+        return this;
+      }
+      public Builder ClearValues() {
+        PrepareBuilder();
+        result.values_.Clear();
+        return this;
+      }
+      
+      public pbc::IPopsicleList<global::UnitTest.Issues.TestProtos.NegativeEnum> PackedValuesList {
+        get { return PrepareBuilder().packedValues_; }
+      }
+      public int PackedValuesCount {
+        get { return result.PackedValuesCount; }
+      }
+      public global::UnitTest.Issues.TestProtos.NegativeEnum GetPackedValues(int index) {
+        return result.GetPackedValues(index);
+      }
+      public Builder SetPackedValues(int index, global::UnitTest.Issues.TestProtos.NegativeEnum value) {
+        PrepareBuilder();
+        result.packedValues_[index] = value;
+        return this;
+      }
+      public Builder AddPackedValues(global::UnitTest.Issues.TestProtos.NegativeEnum value) {
+        PrepareBuilder();
+        result.packedValues_.Add(value);
+        return this;
+      }
+      public Builder AddRangePackedValues(scg::IEnumerable<global::UnitTest.Issues.TestProtos.NegativeEnum> values) {
+        PrepareBuilder();
+        result.packedValues_.Add(values);
+        return this;
+      }
+      public Builder ClearPackedValues() {
+        PrepareBuilder();
+        result.packedValues_.Clear();
+        return this;
+      }
+    }
+    static NegativeEnumMessage() {
+      object.ReferenceEquals(global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.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 DeprecatedChild : pb::GeneratedMessage<DeprecatedChild, DeprecatedChild.Builder> {
+    private DeprecatedChild() { }
+    private static readonly DeprecatedChild defaultInstance = new DeprecatedChild().MakeReadOnly();
+    private static readonly string[] _deprecatedChildFieldNames = new string[] {  };
+    private static readonly uint[] _deprecatedChildFieldTags = new uint[] {  };
+    public static DeprecatedChild DefaultInstance {
+      get { return defaultInstance; }
+    }
+    
+    public override DeprecatedChild DefaultInstanceForType {
+      get { return DefaultInstance; }
+    }
+    
+    protected override DeprecatedChild ThisMessage {
+      get { return this; }
+    }
+    
+    public static pbd::MessageDescriptor Descriptor {
+      get { return global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.internal__static_unittest_issues_DeprecatedChild__Descriptor; }
+    }
+    
+    protected override pb::FieldAccess.FieldAccessorTable<DeprecatedChild, DeprecatedChild.Builder> InternalFieldAccessors {
+      get { return global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.internal__static_unittest_issues_DeprecatedChild__FieldAccessorTable; }
+    }
+    
+    public override bool IsInitialized {
+      get {
+        return true;
+      }
+    }
+    
+    public override void WriteTo(pb::ICodedOutputStream output) {
+      int size = SerializedSize;
+      string[] field_names = _deprecatedChildFieldNames;
+      UnknownFields.WriteTo(output);
+    }
+    
+    private int memoizedSerializedSize = -1;
+    public override int SerializedSize {
+      get {
+        int size = memoizedSerializedSize;
+        if (size != -1) return size;
+        
+        size = 0;
+        size += UnknownFields.SerializedSize;
+        memoizedSerializedSize = size;
+        return size;
+      }
+    }
+    
+    public static DeprecatedChild ParseFrom(pb::ByteString data) {
+      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+    }
+    public static DeprecatedChild ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
+      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+    }
+    public static DeprecatedChild ParseFrom(byte[] data) {
+      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+    }
+    public static DeprecatedChild ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
+      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+    }
+    public static DeprecatedChild ParseFrom(global::System.IO.Stream input) {
+      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+    }
+    public static DeprecatedChild ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
+      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+    }
+    public static DeprecatedChild ParseDelimitedFrom(global::System.IO.Stream input) {
+      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
+    }
+    public static DeprecatedChild ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
+      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
+    }
+    public static DeprecatedChild ParseFrom(pb::ICodedInputStream input) {
+      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+    }
+    public static DeprecatedChild ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+    }
+    private DeprecatedChild 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(DeprecatedChild 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::GeneratedBuilder<DeprecatedChild, Builder> {
+      protected override Builder ThisBuilder {
+        get { return this; }
+      }
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(DeprecatedChild cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
+      
+      private bool resultIsReadOnly;
+      private DeprecatedChild result;
+      
+      private DeprecatedChild PrepareBuilder() {
+        if (resultIsReadOnly) {
+          DeprecatedChild original = result;
+          result = new DeprecatedChild();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
+      
+      protected override DeprecatedChild MessageBeingBuilt {
+        get { return PrepareBuilder(); }
+      }
+      
+      public override Builder Clear() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+        return this;
+      }
+      
+      public override Builder Clone() {
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
+      }
+      
+      public override pbd::MessageDescriptor DescriptorForType {
+        get { return global::UnitTest.Issues.TestProtos.DeprecatedChild.Descriptor; }
+      }
+      
+      public override DeprecatedChild DefaultInstanceForType {
+        get { return global::UnitTest.Issues.TestProtos.DeprecatedChild.DefaultInstance; }
+      }
+      
+      public override DeprecatedChild BuildPartial() {
+        if (resultIsReadOnly) {
+          return result;
+        }
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
+      }
+      
+      public override Builder MergeFrom(pb::IMessage other) {
+        if (other is DeprecatedChild) {
+          return MergeFrom((DeprecatedChild) other);
+        } else {
+          base.MergeFrom(other);
+          return this;
+        }
+      }
+      
+      public override Builder MergeFrom(DeprecatedChild other) {
+        if (other == global::UnitTest.Issues.TestProtos.DeprecatedChild.DefaultInstance) return this;
+        PrepareBuilder();
+        this.MergeUnknownFields(other.UnknownFields);
+        return this;
+      }
+      
+      public override Builder MergeFrom(pb::ICodedInputStream input) {
+        return MergeFrom(input, pb::ExtensionRegistry.Empty);
+      }
+      
+      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
+        pb::UnknownFieldSet.Builder unknownFields = null;
+        uint tag;
+        string field_name;
+        while (input.ReadTag(out tag, out field_name)) {
+          if(tag == 0 && field_name != null) {
+            int field_ordinal = global::System.Array.BinarySearch(_deprecatedChildFieldNames, field_name, global::System.StringComparer.Ordinal);
+            if(field_ordinal >= 0)
+              tag = _deprecatedChildFieldTags[field_ordinal];
+            else {
+              if (unknownFields == null) {
+                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+              }
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+              continue;
+            }
+          }
+          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;
+            }
+          }
+        }
+        
+        if (unknownFields != null) {
+          this.UnknownFields = unknownFields.Build();
+        }
+        return this;
+      }
+      
+    }
+    static DeprecatedChild() {
+      object.ReferenceEquals(global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.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 DeprecatedFieldsMessage : pb::GeneratedMessage<DeprecatedFieldsMessage, DeprecatedFieldsMessage.Builder> {
+    private DeprecatedFieldsMessage() { }
+    private static readonly DeprecatedFieldsMessage defaultInstance = new DeprecatedFieldsMessage().MakeReadOnly();
+    private static readonly string[] _deprecatedFieldsMessageFieldNames = new string[] { "EnumArray", "EnumValue", "MessageArray", "MessageValue", "PrimitiveArray", "PrimitiveValue" };
+    private static readonly uint[] _deprecatedFieldsMessageFieldTags = new uint[] { 48, 40, 34, 26, 16, 8 };
+    public static DeprecatedFieldsMessage DefaultInstance {
+      get { return defaultInstance; }
+    }
+    
+    public override DeprecatedFieldsMessage DefaultInstanceForType {
+      get { return DefaultInstance; }
+    }
+    
+    protected override DeprecatedFieldsMessage ThisMessage {
+      get { return this; }
+    }
+    
+    public static pbd::MessageDescriptor Descriptor {
+      get { return global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.internal__static_unittest_issues_DeprecatedFieldsMessage__Descriptor; }
+    }
+    
+    protected override pb::FieldAccess.FieldAccessorTable<DeprecatedFieldsMessage, DeprecatedFieldsMessage.Builder> InternalFieldAccessors {
+      get { return global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.internal__static_unittest_issues_DeprecatedFieldsMessage__FieldAccessorTable; }
+    }
+    
+    public const int PrimitiveValueFieldNumber = 1;
+    private bool hasPrimitiveValue;
+    private int primitiveValue_;
+    [global::System.ObsoleteAttribute()]
+    public bool HasPrimitiveValue {
+      get { return hasPrimitiveValue; }
+    }
+    [global::System.ObsoleteAttribute()]
+    public int PrimitiveValue {
+      get { return primitiveValue_; }
+    }
+    
+    public const int PrimitiveArrayFieldNumber = 2;
+    private pbc::PopsicleList<int> primitiveArray_ = new pbc::PopsicleList<int>();
+    [global::System.ObsoleteAttribute()]
+    public scg::IList<int> PrimitiveArrayList {
+      get { return pbc::Lists.AsReadOnly(primitiveArray_); }
+    }
+    [global::System.ObsoleteAttribute()]
+    public int PrimitiveArrayCount {
+      get { return primitiveArray_.Count; }
+    }
+    [global::System.ObsoleteAttribute()]
+    public int GetPrimitiveArray(int index) {
+      return primitiveArray_[index];
+    }
+    
+    public const int MessageValueFieldNumber = 3;
+    private bool hasMessageValue;
+    private global::UnitTest.Issues.TestProtos.DeprecatedChild messageValue_;
+    [global::System.ObsoleteAttribute()]
+    public bool HasMessageValue {
+      get { return hasMessageValue; }
+    }
+    [global::System.ObsoleteAttribute()]
+    public global::UnitTest.Issues.TestProtos.DeprecatedChild MessageValue {
+      get { return messageValue_ ?? global::UnitTest.Issues.TestProtos.DeprecatedChild.DefaultInstance; }
+    }
+    
+    public const int MessageArrayFieldNumber = 4;
+    private pbc::PopsicleList<global::UnitTest.Issues.TestProtos.DeprecatedChild> messageArray_ = new pbc::PopsicleList<global::UnitTest.Issues.TestProtos.DeprecatedChild>();
+    [global::System.ObsoleteAttribute()]
+    public scg::IList<global::UnitTest.Issues.TestProtos.DeprecatedChild> MessageArrayList {
+      get { return messageArray_; }
+    }
+    [global::System.ObsoleteAttribute()]
+    public int MessageArrayCount {
+      get { return messageArray_.Count; }
+    }
+    [global::System.ObsoleteAttribute()]
+    public global::UnitTest.Issues.TestProtos.DeprecatedChild GetMessageArray(int index) {
+      return messageArray_[index];
+    }
+    
+    public const int EnumValueFieldNumber = 5;
+    private bool hasEnumValue;
+    private global::UnitTest.Issues.TestProtos.DeprecatedEnum enumValue_ = global::UnitTest.Issues.TestProtos.DeprecatedEnum.one;
+    [global::System.ObsoleteAttribute()]
+    public bool HasEnumValue {
+      get { return hasEnumValue; }
+    }
+    [global::System.ObsoleteAttribute()]
+    public global::UnitTest.Issues.TestProtos.DeprecatedEnum EnumValue {
+      get { return enumValue_; }
+    }
+    
+    public const int EnumArrayFieldNumber = 6;
+    private pbc::PopsicleList<global::UnitTest.Issues.TestProtos.DeprecatedEnum> enumArray_ = new pbc::PopsicleList<global::UnitTest.Issues.TestProtos.DeprecatedEnum>();
+    [global::System.ObsoleteAttribute()]
+    public scg::IList<global::UnitTest.Issues.TestProtos.DeprecatedEnum> EnumArrayList {
+      get { return pbc::Lists.AsReadOnly(enumArray_); }
+    }
+    [global::System.ObsoleteAttribute()]
+    public int EnumArrayCount {
+      get { return enumArray_.Count; }
+    }
+    [global::System.ObsoleteAttribute()]
+    public global::UnitTest.Issues.TestProtos.DeprecatedEnum GetEnumArray(int index) {
+      return enumArray_[index];
+    }
+    
+    public override bool IsInitialized {
+      get {
+        return true;
+      }
+    }
+    
+    public override void WriteTo(pb::ICodedOutputStream output) {
+      int size = SerializedSize;
+      string[] field_names = _deprecatedFieldsMessageFieldNames;
+      if (hasPrimitiveValue) {
+        output.WriteInt32(1, field_names[5], PrimitiveValue);
+      }
+      if (primitiveArray_.Count > 0) {
+        output.WriteInt32Array(2, field_names[4], primitiveArray_);
+      }
+      if (hasMessageValue) {
+        output.WriteMessage(3, field_names[3], MessageValue);
+      }
+      if (messageArray_.Count > 0) {
+        output.WriteMessageArray(4, field_names[2], messageArray_);
+      }
+      if (hasEnumValue) {
+        output.WriteEnum(5, field_names[1], (int) EnumValue, EnumValue);
+      }
+      if (enumArray_.Count > 0) {
+        output.WriteEnumArray(6, field_names[0], enumArray_);
+      }
+      UnknownFields.WriteTo(output);
+    }
+    
+    private int memoizedSerializedSize = -1;
+    public override int SerializedSize {
+      get {
+        int size = memoizedSerializedSize;
+        if (size != -1) return size;
+        
+        size = 0;
+        if (hasPrimitiveValue) {
+          size += pb::CodedOutputStream.ComputeInt32Size(1, PrimitiveValue);
+        }
+        {
+          int dataSize = 0;
+          foreach (int element in PrimitiveArrayList) {
+            dataSize += pb::CodedOutputStream.ComputeInt32SizeNoTag(element);
+          }
+          size += dataSize;
+          size += 1 * primitiveArray_.Count;
+        }
+        if (hasMessageValue) {
+          size += pb::CodedOutputStream.ComputeMessageSize(3, MessageValue);
+        }
+        foreach (global::UnitTest.Issues.TestProtos.DeprecatedChild element in MessageArrayList) {
+          size += pb::CodedOutputStream.ComputeMessageSize(4, element);
+        }
+        if (hasEnumValue) {
+          size += pb::CodedOutputStream.ComputeEnumSize(5, (int) EnumValue);
+        }
+        {
+          int dataSize = 0;
+          if (enumArray_.Count > 0) {
+            foreach (global::UnitTest.Issues.TestProtos.DeprecatedEnum element in enumArray_) {
+              dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element);
+            }
+            size += dataSize;
+            size += 1 * enumArray_.Count;
+          }
+        }
+        size += UnknownFields.SerializedSize;
+        memoizedSerializedSize = size;
+        return size;
+      }
+    }
+    
+    public static DeprecatedFieldsMessage ParseFrom(pb::ByteString data) {
+      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+    }
+    public static DeprecatedFieldsMessage ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
+      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+    }
+    public static DeprecatedFieldsMessage ParseFrom(byte[] data) {
+      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+    }
+    public static DeprecatedFieldsMessage ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
+      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+    }
+    public static DeprecatedFieldsMessage ParseFrom(global::System.IO.Stream input) {
+      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+    }
+    public static DeprecatedFieldsMessage ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
+      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+    }
+    public static DeprecatedFieldsMessage ParseDelimitedFrom(global::System.IO.Stream input) {
+      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
+    }
+    public static DeprecatedFieldsMessage ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
+      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
+    }
+    public static DeprecatedFieldsMessage ParseFrom(pb::ICodedInputStream input) {
+      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+    }
+    public static DeprecatedFieldsMessage ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+    }
+    private DeprecatedFieldsMessage MakeReadOnly() {
+      primitiveArray_.MakeReadOnly();
+      messageArray_.MakeReadOnly();
+      enumArray_.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(DeprecatedFieldsMessage 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::GeneratedBuilder<DeprecatedFieldsMessage, Builder> {
+      protected override Builder ThisBuilder {
+        get { return this; }
+      }
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(DeprecatedFieldsMessage cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
+      
+      private bool resultIsReadOnly;
+      private DeprecatedFieldsMessage result;
+      
+      private DeprecatedFieldsMessage PrepareBuilder() {
+        if (resultIsReadOnly) {
+          DeprecatedFieldsMessage original = result;
+          result = new DeprecatedFieldsMessage();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
+      
+      protected override DeprecatedFieldsMessage MessageBeingBuilt {
+        get { return PrepareBuilder(); }
+      }
+      
+      public override Builder Clear() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+        return this;
+      }
+      
+      public override Builder Clone() {
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
+      }
+      
+      public override pbd::MessageDescriptor DescriptorForType {
+        get { return global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage.Descriptor; }
+      }
+      
+      public override DeprecatedFieldsMessage DefaultInstanceForType {
+        get { return global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage.DefaultInstance; }
+      }
+      
+      public override DeprecatedFieldsMessage BuildPartial() {
+        if (resultIsReadOnly) {
+          return result;
+        }
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
+      }
+      
+      public override Builder MergeFrom(pb::IMessage other) {
+        if (other is DeprecatedFieldsMessage) {
+          return MergeFrom((DeprecatedFieldsMessage) other);
+        } else {
+          base.MergeFrom(other);
+          return this;
+        }
+      }
+      
+      public override Builder MergeFrom(DeprecatedFieldsMessage other) {
+        if (other == global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage.DefaultInstance) return this;
+        PrepareBuilder();
+        if (other.HasPrimitiveValue) {
+          PrimitiveValue = other.PrimitiveValue;
+        }
+        if (other.primitiveArray_.Count != 0) {
+          result.primitiveArray_.Add(other.primitiveArray_);
+        }
+        if (other.HasMessageValue) {
+          MergeMessageValue(other.MessageValue);
+        }
+        if (other.messageArray_.Count != 0) {
+          result.messageArray_.Add(other.messageArray_);
+        }
+        if (other.HasEnumValue) {
+          EnumValue = other.EnumValue;
+        }
+        if (other.enumArray_.Count != 0) {
+          result.enumArray_.Add(other.enumArray_);
+        }
+        this.MergeUnknownFields(other.UnknownFields);
+        return this;
+      }
+      
+      public override Builder MergeFrom(pb::ICodedInputStream input) {
+        return MergeFrom(input, pb::ExtensionRegistry.Empty);
+      }
+      
+      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
+        pb::UnknownFieldSet.Builder unknownFields = null;
+        uint tag;
+        string field_name;
+        while (input.ReadTag(out tag, out field_name)) {
+          if(tag == 0 && field_name != null) {
+            int field_ordinal = global::System.Array.BinarySearch(_deprecatedFieldsMessageFieldNames, field_name, global::System.StringComparer.Ordinal);
+            if(field_ordinal >= 0)
+              tag = _deprecatedFieldsMessageFieldTags[field_ordinal];
+            else {
+              if (unknownFields == null) {
+                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+              }
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+              continue;
+            }
+          }
+          switch (tag) {
+            case 0: {
+              throw pb::InvalidProtocolBufferException.InvalidTag();
+            }
+            default: {
+              if (pb::WireFormat.IsEndGroupTag(tag)) {
+                if (unknownFields != null) {
+                  this.UnknownFields = unknownFields.Build();
+                }
+                return this;
+              }
+              if (unknownFields == null) {
+                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+              }
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+              break;
+            }
+            case 8: {
+              result.hasPrimitiveValue = input.ReadInt32(ref result.primitiveValue_);
+              break;
+            }
+            case 18:
+            case 16: {
+              input.ReadInt32Array(tag, field_name, result.primitiveArray_);
+              break;
+            }
+            case 26: {
+              global::UnitTest.Issues.TestProtos.DeprecatedChild.Builder subBuilder = global::UnitTest.Issues.TestProtos.DeprecatedChild.CreateBuilder();
+              if (result.hasMessageValue) {
+                subBuilder.MergeFrom(MessageValue);
+              }
+              input.ReadMessage(subBuilder, extensionRegistry);
+              MessageValue = subBuilder.BuildPartial();
+              break;
+            }
+            case 34: {
+              input.ReadMessageArray(tag, field_name, result.messageArray_, global::UnitTest.Issues.TestProtos.DeprecatedChild.DefaultInstance, extensionRegistry);
+              break;
+            }
+            case 40: {
+              object unknown;
+              if(input.ReadEnum(ref result.enumValue_, out unknown)) {
+                result.hasEnumValue = true;
+              } else if(unknown is int) {
+                if (unknownFields == null) {
+                  unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+                }
+                unknownFields.MergeVarintField(5, (ulong)(int)unknown);
+              }
+              break;
+            }
+            case 50:
+            case 48: {
+              scg::ICollection<object> unknownItems;
+              input.ReadEnumArray<global::UnitTest.Issues.TestProtos.DeprecatedEnum>(tag, field_name, result.enumArray_, out unknownItems);
+              if (unknownItems != null) {
+                if (unknownFields == null) {
+                  unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+                }
+                foreach (object rawValue in unknownItems)
+                  if (rawValue is int)
+                    unknownFields.MergeVarintField(6, (ulong)(int)rawValue);
+              }
+              break;
+            }
+          }
+        }
+        
+        if (unknownFields != null) {
+          this.UnknownFields = unknownFields.Build();
+        }
+        return this;
+      }
+      
+      
+      [global::System.ObsoleteAttribute()]
+      public bool HasPrimitiveValue {
+        get { return result.hasPrimitiveValue; }
+      }
+      [global::System.ObsoleteAttribute()]
+      public int PrimitiveValue {
+        get { return result.PrimitiveValue; }
+        set { SetPrimitiveValue(value); }
+      }
+      [global::System.ObsoleteAttribute()]
+      public Builder SetPrimitiveValue(int value) {
+        PrepareBuilder();
+        result.hasPrimitiveValue = true;
+        result.primitiveValue_ = value;
+        return this;
+      }
+      [global::System.ObsoleteAttribute()]
+      public Builder ClearPrimitiveValue() {
+        PrepareBuilder();
+        result.hasPrimitiveValue = false;
+        result.primitiveValue_ = 0;
+        return this;
+      }
+      
+      [global::System.ObsoleteAttribute()]
+      public pbc::IPopsicleList<int> PrimitiveArrayList {
+        get { return PrepareBuilder().primitiveArray_; }
+      }
+      [global::System.ObsoleteAttribute()]
+      public int PrimitiveArrayCount {
+        get { return result.PrimitiveArrayCount; }
+      }
+      [global::System.ObsoleteAttribute()]
+      public int GetPrimitiveArray(int index) {
+        return result.GetPrimitiveArray(index);
+      }
+      [global::System.ObsoleteAttribute()]
+      public Builder SetPrimitiveArray(int index, int value) {
+        PrepareBuilder();
+        result.primitiveArray_[index] = value;
+        return this;
+      }
+      [global::System.ObsoleteAttribute()]
+      public Builder AddPrimitiveArray(int value) {
+        PrepareBuilder();
+        result.primitiveArray_.Add(value);
+        return this;
+      }
+      [global::System.ObsoleteAttribute()]
+      public Builder AddRangePrimitiveArray(scg::IEnumerable<int> values) {
+        PrepareBuilder();
+        result.primitiveArray_.Add(values);
+        return this;
+      }
+      [global::System.ObsoleteAttribute()]
+      public Builder ClearPrimitiveArray() {
+        PrepareBuilder();
+        result.primitiveArray_.Clear();
+        return this;
+      }
+      
+      [global::System.ObsoleteAttribute()]
+      public bool HasMessageValue {
+       get { return result.hasMessageValue; }
+      }
+      [global::System.ObsoleteAttribute()]
+      public global::UnitTest.Issues.TestProtos.DeprecatedChild MessageValue {
+        get { return result.MessageValue; }
+        set { SetMessageValue(value); }
+      }
+      [global::System.ObsoleteAttribute()]
+      public Builder SetMessageValue(global::UnitTest.Issues.TestProtos.DeprecatedChild value) {
+        pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
+        result.hasMessageValue = true;
+        result.messageValue_ = value;
+        return this;
+      }
+      [global::System.ObsoleteAttribute()]
+      public Builder SetMessageValue(global::UnitTest.Issues.TestProtos.DeprecatedChild.Builder builderForValue) {
+        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
+        result.hasMessageValue = true;
+        result.messageValue_ = builderForValue.Build();
+        return this;
+      }
+      [global::System.ObsoleteAttribute()]
+      public Builder MergeMessageValue(global::UnitTest.Issues.TestProtos.DeprecatedChild value) {
+        pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
+        if (result.hasMessageValue &&
+            result.messageValue_ != global::UnitTest.Issues.TestProtos.DeprecatedChild.DefaultInstance) {
+            result.messageValue_ = global::UnitTest.Issues.TestProtos.DeprecatedChild.CreateBuilder(result.messageValue_).MergeFrom(value).BuildPartial();
+        } else {
+          result.messageValue_ = value;
+        }
+        result.hasMessageValue = true;
+        return this;
+      }
+      [global::System.ObsoleteAttribute()]
+      public Builder ClearMessageValue() {
+        PrepareBuilder();
+        result.hasMessageValue = false;
+        result.messageValue_ = null;
+        return this;
+      }
+      
+      [global::System.ObsoleteAttribute()]
+      public pbc::IPopsicleList<global::UnitTest.Issues.TestProtos.DeprecatedChild> MessageArrayList {
+        get { return PrepareBuilder().messageArray_; }
+      }
+      [global::System.ObsoleteAttribute()]
+      public int MessageArrayCount {
+        get { return result.MessageArrayCount; }
+      }
+      [global::System.ObsoleteAttribute()]
+      public global::UnitTest.Issues.TestProtos.DeprecatedChild GetMessageArray(int index) {
+        return result.GetMessageArray(index);
+      }
+      [global::System.ObsoleteAttribute()]
+      public Builder SetMessageArray(int index, global::UnitTest.Issues.TestProtos.DeprecatedChild value) {
+        pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
+        result.messageArray_[index] = value;
+        return this;
+      }
+      [global::System.ObsoleteAttribute()]
+      public Builder SetMessageArray(int index, global::UnitTest.Issues.TestProtos.DeprecatedChild.Builder builderForValue) {
+        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
+        result.messageArray_[index] = builderForValue.Build();
+        return this;
+      }
+      [global::System.ObsoleteAttribute()]
+      public Builder AddMessageArray(global::UnitTest.Issues.TestProtos.DeprecatedChild value) {
+        pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
+        result.messageArray_.Add(value);
+        return this;
+      }
+      [global::System.ObsoleteAttribute()]
+      public Builder AddMessageArray(global::UnitTest.Issues.TestProtos.DeprecatedChild.Builder builderForValue) {
+        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
+        result.messageArray_.Add(builderForValue.Build());
+        return this;
+      }
+      [global::System.ObsoleteAttribute()]
+      public Builder AddRangeMessageArray(scg::IEnumerable<global::UnitTest.Issues.TestProtos.DeprecatedChild> values) {
+        PrepareBuilder();
+        result.messageArray_.Add(values);
+        return this;
+      }
+      [global::System.ObsoleteAttribute()]
+      public Builder ClearMessageArray() {
+        PrepareBuilder();
+        result.messageArray_.Clear();
+        return this;
+      }
+      
+      [global::System.ObsoleteAttribute()]
+      public bool HasEnumValue {
+       get { return result.hasEnumValue; }
+      }
+      [global::System.ObsoleteAttribute()]
+      public global::UnitTest.Issues.TestProtos.DeprecatedEnum EnumValue {
+        get { return result.EnumValue; }
+        set { SetEnumValue(value); }
+      }
+      [global::System.ObsoleteAttribute()]
+      public Builder SetEnumValue(global::UnitTest.Issues.TestProtos.DeprecatedEnum value) {
+        PrepareBuilder();
+        result.hasEnumValue = true;
+        result.enumValue_ = value;
+        return this;
+      }
+      [global::System.ObsoleteAttribute()]
+      public Builder ClearEnumValue() {
+        PrepareBuilder();
+        result.hasEnumValue = false;
+        result.enumValue_ = global::UnitTest.Issues.TestProtos.DeprecatedEnum.one;
+        return this;
+      }
+      
+      [global::System.ObsoleteAttribute()]
+      public pbc::IPopsicleList<global::UnitTest.Issues.TestProtos.DeprecatedEnum> EnumArrayList {
+        get { return PrepareBuilder().enumArray_; }
+      }
+      [global::System.ObsoleteAttribute()]
+      public int EnumArrayCount {
+        get { return result.EnumArrayCount; }
+      }
+      [global::System.ObsoleteAttribute()]
+      public global::UnitTest.Issues.TestProtos.DeprecatedEnum GetEnumArray(int index) {
+        return result.GetEnumArray(index);
+      }
+      [global::System.ObsoleteAttribute()]
+      public Builder SetEnumArray(int index, global::UnitTest.Issues.TestProtos.DeprecatedEnum value) {
+        PrepareBuilder();
+        result.enumArray_[index] = value;
+        return this;
+      }
+      [global::System.ObsoleteAttribute()]
+      public Builder AddEnumArray(global::UnitTest.Issues.TestProtos.DeprecatedEnum value) {
+        PrepareBuilder();
+        result.enumArray_.Add(value);
+        return this;
+      }
+      [global::System.ObsoleteAttribute()]
+      public Builder AddRangeEnumArray(scg::IEnumerable<global::UnitTest.Issues.TestProtos.DeprecatedEnum> values) {
+        PrepareBuilder();
+        result.enumArray_.Add(values);
+        return this;
+      }
+      [global::System.ObsoleteAttribute()]
+      public Builder ClearEnumArray() {
+        PrepareBuilder();
+        result.enumArray_.Clear();
+        return this;
+      }
+    }
+    static DeprecatedFieldsMessage() {
+      object.ReferenceEquals(global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.Descriptor, null);
+    }
+  }
+  
   #endregion
   
 }

+ 1 - 1
src/ProtocolBuffers.Test/TestProtos/UnitTestGenericServices.cs

@@ -1,5 +1,5 @@
 // Generated by ProtoGen, Version=2.3.0.277, Culture=neutral, PublicKeyToken=17b3b1f090c3ea48.  DO NOT EDIT!
-#pragma warning disable 1591
+#pragma warning disable 1591, 0612
 #region Designer generated code
 
 using pb = global::Google.ProtocolBuffers;

Plik diff jest za duży
+ 203 - 33
src/ProtocolBuffers.Test/TestProtos/UnitTestGoogleSizeProtoFile.cs


Plik diff jest za duży
+ 202 - 34
src/ProtocolBuffers.Test/TestProtos/UnitTestGoogleSpeedProtoFile.cs


+ 49 - 14
src/ProtocolBuffers.Test/TestProtos/UnitTestImportLiteProtoFile.cs

@@ -1,5 +1,5 @@
 // Generated by ProtoGen, Version=2.3.0.277, Culture=neutral, PublicKeyToken=17b3b1f090c3ea48.  DO NOT EDIT!
-#pragma warning disable 1591
+#pragma warning disable 1591, 0612
 #region Designer generated code
 
 using pb = global::Google.ProtocolBuffers;
@@ -43,7 +43,8 @@ namespace Google.ProtocolBuffers.TestProtos {
   [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
   [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
   public sealed partial class ImportMessageLite : pb::GeneratedMessageLite<ImportMessageLite, ImportMessageLite.Builder> {
-    private static readonly ImportMessageLite defaultInstance = new Builder().BuildPartial();
+    private ImportMessageLite() { }
+    private static readonly ImportMessageLite defaultInstance = new ImportMessageLite().MakeReadOnly();
     private static readonly string[] _importMessageLiteFieldNames = new string[] { "d" };
     private static readonly uint[] _importMessageLiteFieldTags = new uint[] { 8 };
     public static ImportMessageLite DefaultInstance {
@@ -51,7 +52,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     }
     
     public override ImportMessageLite DefaultInstanceForType {
-      get { return defaultInstance; }
+      get { return DefaultInstance; }
     }
     
     protected override ImportMessageLite ThisMessage {
@@ -146,11 +147,15 @@ namespace Google.ProtocolBuffers.TestProtos {
     public static ImportMessageLite ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
       return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
     }
+    private ImportMessageLite 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(ImportMessageLite prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -160,21 +165,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(ImportMessageLite cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
+      
+      private bool resultIsReadOnly;
+      private ImportMessageLite result;
+      
+      private ImportMessageLite PrepareBuilder() {
+        if (resultIsReadOnly) {
+          ImportMessageLite original = result;
+          result = new ImportMessageLite();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
       
-      ImportMessageLite result = new ImportMessageLite();
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override ImportMessageLite MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new ImportMessageLite();
+        result = DefaultInstance;
+        resultIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override ImportMessageLite DefaultInstanceForType {
@@ -182,12 +214,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override ImportMessageLite BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (resultIsReadOnly) {
+          return result;
         }
-        ImportMessageLite returnMe = result;
-        result = null;
-        return returnMe;
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
       }
       
       public override Builder MergeFrom(pb::IMessageLite other) {
@@ -201,6 +232,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(ImportMessageLite other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.ImportMessageLite.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasD) {
           D = other.D;
         }
@@ -212,6 +244,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         uint tag;
         string field_name;
         while (input.ReadTag(out tag, out field_name)) {
@@ -254,11 +287,13 @@ namespace Google.ProtocolBuffers.TestProtos {
         set { SetD(value); }
       }
       public Builder SetD(int value) {
+        PrepareBuilder();
         result.hasD = true;
         result.d_ = value;
         return this;
       }
       public Builder ClearD() {
+        PrepareBuilder();
         result.hasD = false;
         result.d_ = 0;
         return this;

+ 49 - 14
src/ProtocolBuffers.Test/TestProtos/UnitTestImportProtoFile.cs

@@ -1,5 +1,5 @@
 // Generated by ProtoGen, Version=2.3.0.277, Culture=neutral, PublicKeyToken=17b3b1f090c3ea48.  DO NOT EDIT!
-#pragma warning disable 1591
+#pragma warning disable 1591, 0612
 #region Designer generated code
 
 using pb = global::Google.ProtocolBuffers;
@@ -71,7 +71,8 @@ namespace Google.ProtocolBuffers.TestProtos {
   [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
   [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
   public sealed partial class ImportMessage : pb::GeneratedMessage<ImportMessage, ImportMessage.Builder> {
-    private static readonly ImportMessage defaultInstance = new Builder().BuildPartial();
+    private ImportMessage() { }
+    private static readonly ImportMessage defaultInstance = new ImportMessage().MakeReadOnly();
     private static readonly string[] _importMessageFieldNames = new string[] { "d" };
     private static readonly uint[] _importMessageFieldTags = new uint[] { 8 };
     public static ImportMessage DefaultInstance {
@@ -79,7 +80,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     }
     
     public override ImportMessage DefaultInstanceForType {
-      get { return defaultInstance; }
+      get { return DefaultInstance; }
     }
     
     protected override ImportMessage ThisMessage {
@@ -165,11 +166,15 @@ namespace Google.ProtocolBuffers.TestProtos {
     public static ImportMessage ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
       return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
     }
+    private ImportMessage 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(ImportMessage prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -179,21 +184,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(ImportMessage cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
+      
+      private bool resultIsReadOnly;
+      private ImportMessage result;
+      
+      private ImportMessage PrepareBuilder() {
+        if (resultIsReadOnly) {
+          ImportMessage original = result;
+          result = new ImportMessage();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
       
-      ImportMessage result = new ImportMessage();
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override ImportMessage MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new ImportMessage();
+        result = DefaultInstance;
+        resultIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -205,12 +237,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override ImportMessage BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (resultIsReadOnly) {
+          return result;
         }
-        ImportMessage returnMe = result;
-        result = null;
-        return returnMe;
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -224,6 +255,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(ImportMessage other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.ImportMessage.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasD) {
           D = other.D;
         }
@@ -236,6 +268,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -291,11 +324,13 @@ namespace Google.ProtocolBuffers.TestProtos {
         set { SetD(value); }
       }
       public Builder SetD(int value) {
+        PrepareBuilder();
         result.hasD = true;
         result.d_ = value;
         return this;
       }
       public Builder ClearD() {
+        PrepareBuilder();
         result.hasD = false;
         result.d_ = 0;
         return this;

+ 302 - 86
src/ProtocolBuffers.Test/TestProtos/UnitTestMessageSetProtoFile.cs

@@ -1,5 +1,5 @@
 // Generated by ProtoGen, Version=2.3.0.277, Culture=neutral, PublicKeyToken=17b3b1f090c3ea48.  DO NOT EDIT!
-#pragma warning disable 1591
+#pragma warning disable 1591, 0612
 #region Designer generated code
 
 using pb = global::Google.ProtocolBuffers;
@@ -103,7 +103,8 @@ namespace Google.ProtocolBuffers.TestProtos {
   [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
   [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
   public sealed partial class TestMessageSet : pb::ExtendableMessage<TestMessageSet, TestMessageSet.Builder> {
-    private static readonly TestMessageSet defaultInstance = new Builder().BuildPartial();
+    private TestMessageSet() { }
+    private static readonly TestMessageSet defaultInstance = new TestMessageSet().MakeReadOnly();
     private static readonly string[] _testMessageSetFieldNames = new string[] {  };
     private static readonly uint[] _testMessageSetFieldTags = new uint[] {  };
     public static TestMessageSet DefaultInstance {
@@ -111,7 +112,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     }
     
     public override TestMessageSet DefaultInstanceForType {
-      get { return defaultInstance; }
+      get { return DefaultInstance; }
     }
     
     protected override TestMessageSet ThisMessage {
@@ -185,11 +186,15 @@ namespace Google.ProtocolBuffers.TestProtos {
     public static TestMessageSet ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
       return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
     }
+    private TestMessageSet 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(TestMessageSet prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -199,21 +204,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(TestMessageSet cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
       
-      TestMessageSet result = new TestMessageSet();
+      private bool resultIsReadOnly;
+      private TestMessageSet result;
+      
+      private TestMessageSet PrepareBuilder() {
+        if (resultIsReadOnly) {
+          TestMessageSet original = result;
+          result = new TestMessageSet();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override TestMessageSet MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new TestMessageSet();
+        result = DefaultInstance;
+        resultIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -225,12 +257,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override TestMessageSet BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (resultIsReadOnly) {
+          return result;
         }
-        TestMessageSet returnMe = result;
-        result = null;
-        return returnMe;
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -244,6 +275,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(TestMessageSet other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.TestMessageSet.DefaultInstance) return this;
+        PrepareBuilder();
           this.MergeExtensionFields(other);
         this.MergeUnknownFields(other.UnknownFields);
         return this;
@@ -254,6 +286,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -306,7 +339,8 @@ namespace Google.ProtocolBuffers.TestProtos {
   [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
   [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
   public sealed partial class TestMessageSetContainer : pb::GeneratedMessage<TestMessageSetContainer, TestMessageSetContainer.Builder> {
-    private static readonly TestMessageSetContainer defaultInstance = new Builder().BuildPartial();
+    private TestMessageSetContainer() { }
+    private static readonly TestMessageSetContainer defaultInstance = new TestMessageSetContainer().MakeReadOnly();
     private static readonly string[] _testMessageSetContainerFieldNames = new string[] { "message_set" };
     private static readonly uint[] _testMessageSetContainerFieldTags = new uint[] { 10 };
     public static TestMessageSetContainer DefaultInstance {
@@ -314,7 +348,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     }
     
     public override TestMessageSetContainer DefaultInstanceForType {
-      get { return defaultInstance; }
+      get { return DefaultInstance; }
     }
     
     protected override TestMessageSetContainer ThisMessage {
@@ -331,12 +365,12 @@ namespace Google.ProtocolBuffers.TestProtos {
     
     public const int MessageSetFieldNumber = 1;
     private bool hasMessageSet;
-    private global::Google.ProtocolBuffers.TestProtos.TestMessageSet messageSet_ = global::Google.ProtocolBuffers.TestProtos.TestMessageSet.DefaultInstance;
+    private global::Google.ProtocolBuffers.TestProtos.TestMessageSet messageSet_;
     public bool HasMessageSet {
       get { return hasMessageSet; }
     }
     public global::Google.ProtocolBuffers.TestProtos.TestMessageSet MessageSet {
-      get { return messageSet_; }
+      get { return messageSet_ ?? global::Google.ProtocolBuffers.TestProtos.TestMessageSet.DefaultInstance; }
     }
     
     public override bool IsInitialized {
@@ -400,11 +434,15 @@ namespace Google.ProtocolBuffers.TestProtos {
     public static TestMessageSetContainer ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
       return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
     }
+    private TestMessageSetContainer 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(TestMessageSetContainer prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -414,21 +452,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(TestMessageSetContainer cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
       
-      TestMessageSetContainer result = new TestMessageSetContainer();
+      private bool resultIsReadOnly;
+      private TestMessageSetContainer result;
+      
+      private TestMessageSetContainer PrepareBuilder() {
+        if (resultIsReadOnly) {
+          TestMessageSetContainer original = result;
+          result = new TestMessageSetContainer();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override TestMessageSetContainer MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new TestMessageSetContainer();
+        result = DefaultInstance;
+        resultIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -440,12 +505,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override TestMessageSetContainer BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (resultIsReadOnly) {
+          return result;
         }
-        TestMessageSetContainer returnMe = result;
-        result = null;
-        return returnMe;
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -459,6 +523,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(TestMessageSetContainer other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.TestMessageSetContainer.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasMessageSet) {
           MergeMessageSet(other.MessageSet);
         }
@@ -471,6 +536,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -532,18 +598,21 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetMessageSet(global::Google.ProtocolBuffers.TestProtos.TestMessageSet value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasMessageSet = true;
         result.messageSet_ = value;
         return this;
       }
       public Builder SetMessageSet(global::Google.ProtocolBuffers.TestProtos.TestMessageSet.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.hasMessageSet = true;
         result.messageSet_ = builderForValue.Build();
         return this;
       }
       public Builder MergeMessageSet(global::Google.ProtocolBuffers.TestProtos.TestMessageSet value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         if (result.hasMessageSet &&
             result.messageSet_ != global::Google.ProtocolBuffers.TestProtos.TestMessageSet.DefaultInstance) {
             result.messageSet_ = global::Google.ProtocolBuffers.TestProtos.TestMessageSet.CreateBuilder(result.messageSet_).MergeFrom(value).BuildPartial();
@@ -554,8 +623,9 @@ namespace Google.ProtocolBuffers.TestProtos {
         return this;
       }
       public Builder ClearMessageSet() {
+        PrepareBuilder();
         result.hasMessageSet = false;
-        result.messageSet_ = global::Google.ProtocolBuffers.TestProtos.TestMessageSet.DefaultInstance;
+        result.messageSet_ = null;
         return this;
       }
     }
@@ -568,7 +638,8 @@ namespace Google.ProtocolBuffers.TestProtos {
   [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
   [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
   public sealed partial class TestMessageSetExtension1 : pb::GeneratedMessage<TestMessageSetExtension1, TestMessageSetExtension1.Builder> {
-    private static readonly TestMessageSetExtension1 defaultInstance = new Builder().BuildPartial();
+    private TestMessageSetExtension1() { }
+    private static readonly TestMessageSetExtension1 defaultInstance = new TestMessageSetExtension1().MakeReadOnly();
     private static readonly string[] _testMessageSetExtension1FieldNames = new string[] { "i" };
     private static readonly uint[] _testMessageSetExtension1FieldTags = new uint[] { 120 };
     public static TestMessageSetExtension1 DefaultInstance {
@@ -576,7 +647,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     }
     
     public override TestMessageSetExtension1 DefaultInstanceForType {
-      get { return defaultInstance; }
+      get { return DefaultInstance; }
     }
     
     protected override TestMessageSetExtension1 ThisMessage {
@@ -664,11 +735,15 @@ namespace Google.ProtocolBuffers.TestProtos {
     public static TestMessageSetExtension1 ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
       return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
     }
+    private TestMessageSetExtension1 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(TestMessageSetExtension1 prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -678,21 +753,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(TestMessageSetExtension1 cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
       
-      TestMessageSetExtension1 result = new TestMessageSetExtension1();
+      private bool resultIsReadOnly;
+      private TestMessageSetExtension1 result;
+      
+      private TestMessageSetExtension1 PrepareBuilder() {
+        if (resultIsReadOnly) {
+          TestMessageSetExtension1 original = result;
+          result = new TestMessageSetExtension1();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override TestMessageSetExtension1 MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new TestMessageSetExtension1();
+        result = DefaultInstance;
+        resultIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -704,12 +806,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override TestMessageSetExtension1 BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (resultIsReadOnly) {
+          return result;
         }
-        TestMessageSetExtension1 returnMe = result;
-        result = null;
-        return returnMe;
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -723,6 +824,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(TestMessageSetExtension1 other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.TestMessageSetExtension1.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasI) {
           I = other.I;
         }
@@ -735,6 +837,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -790,11 +893,13 @@ namespace Google.ProtocolBuffers.TestProtos {
         set { SetI(value); }
       }
       public Builder SetI(int value) {
+        PrepareBuilder();
         result.hasI = true;
         result.i_ = value;
         return this;
       }
       public Builder ClearI() {
+        PrepareBuilder();
         result.hasI = false;
         result.i_ = 0;
         return this;
@@ -809,7 +914,8 @@ namespace Google.ProtocolBuffers.TestProtos {
   [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
   [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
   public sealed partial class TestMessageSetExtension2 : pb::GeneratedMessage<TestMessageSetExtension2, TestMessageSetExtension2.Builder> {
-    private static readonly TestMessageSetExtension2 defaultInstance = new Builder().BuildPartial();
+    private TestMessageSetExtension2() { }
+    private static readonly TestMessageSetExtension2 defaultInstance = new TestMessageSetExtension2().MakeReadOnly();
     private static readonly string[] _testMessageSetExtension2FieldNames = new string[] { "str" };
     private static readonly uint[] _testMessageSetExtension2FieldTags = new uint[] { 202 };
     public static TestMessageSetExtension2 DefaultInstance {
@@ -817,7 +923,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     }
     
     public override TestMessageSetExtension2 DefaultInstanceForType {
-      get { return defaultInstance; }
+      get { return DefaultInstance; }
     }
     
     protected override TestMessageSetExtension2 ThisMessage {
@@ -905,11 +1011,15 @@ namespace Google.ProtocolBuffers.TestProtos {
     public static TestMessageSetExtension2 ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
       return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
     }
+    private TestMessageSetExtension2 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(TestMessageSetExtension2 prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -919,21 +1029,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(TestMessageSetExtension2 cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
+      
+      private bool resultIsReadOnly;
+      private TestMessageSetExtension2 result;
       
-      TestMessageSetExtension2 result = new TestMessageSetExtension2();
+      private TestMessageSetExtension2 PrepareBuilder() {
+        if (resultIsReadOnly) {
+          TestMessageSetExtension2 original = result;
+          result = new TestMessageSetExtension2();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override TestMessageSetExtension2 MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new TestMessageSetExtension2();
+        result = DefaultInstance;
+        resultIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -945,12 +1082,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override TestMessageSetExtension2 BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (resultIsReadOnly) {
+          return result;
         }
-        TestMessageSetExtension2 returnMe = result;
-        result = null;
-        return returnMe;
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -964,6 +1100,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(TestMessageSetExtension2 other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.TestMessageSetExtension2.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasStr) {
           Str = other.Str;
         }
@@ -976,6 +1113,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -1032,11 +1170,13 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetStr(string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasStr = true;
         result.str_ = value;
         return this;
       }
       public Builder ClearStr() {
+        PrepareBuilder();
         result.hasStr = false;
         result.str_ = "";
         return this;
@@ -1051,7 +1191,8 @@ namespace Google.ProtocolBuffers.TestProtos {
   [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
   [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
   public sealed partial class RawMessageSet : pb::GeneratedMessage<RawMessageSet, RawMessageSet.Builder> {
-    private static readonly RawMessageSet defaultInstance = new Builder().BuildPartial();
+    private RawMessageSet() { }
+    private static readonly RawMessageSet defaultInstance = new RawMessageSet().MakeReadOnly();
     private static readonly string[] _rawMessageSetFieldNames = new string[] { "item" };
     private static readonly uint[] _rawMessageSetFieldTags = new uint[] { 11 };
     public static RawMessageSet DefaultInstance {
@@ -1059,7 +1200,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     }
     
     public override RawMessageSet DefaultInstanceForType {
-      get { return defaultInstance; }
+      get { return DefaultInstance; }
     }
     
     protected override RawMessageSet ThisMessage {
@@ -1083,7 +1224,8 @@ namespace Google.ProtocolBuffers.TestProtos {
       [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
       [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
       public sealed partial class Item : pb::GeneratedMessage<Item, Item.Builder> {
-        private static readonly Item defaultInstance = new Builder().BuildPartial();
+        private Item() { }
+        private static readonly Item defaultInstance = new Item().MakeReadOnly();
         private static readonly string[] _itemFieldNames = new string[] { "message", "type_id" };
         private static readonly uint[] _itemFieldTags = new uint[] { 26, 16 };
         public static Item DefaultInstance {
@@ -1091,7 +1233,7 @@ namespace Google.ProtocolBuffers.TestProtos {
         }
         
         public override Item DefaultInstanceForType {
-          get { return defaultInstance; }
+          get { return DefaultInstance; }
         }
         
         protected override Item ThisMessage {
@@ -1195,11 +1337,15 @@ namespace Google.ProtocolBuffers.TestProtos {
         public static Item ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
           return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
         }
+        private Item 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(Item prototype) {
-          return (Builder) new Builder().MergeFrom(prototype);
+          return new Builder(prototype);
         }
         
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -1209,21 +1355,48 @@ namespace Google.ProtocolBuffers.TestProtos {
           protected override Builder ThisBuilder {
             get { return this; }
           }
-          public Builder() {}
+          public Builder() {
+            result = DefaultInstance;
+            resultIsReadOnly = true;
+          }
+          internal Builder(Item cloneFrom) {
+            result = cloneFrom;
+            resultIsReadOnly = true;
+          }
           
-          Item result = new Item();
+          private bool resultIsReadOnly;
+          private Item result;
+          
+          private Item PrepareBuilder() {
+            if (resultIsReadOnly) {
+              Item original = result;
+              result = new Item();
+              resultIsReadOnly = false;
+              MergeFrom(original);
+            }
+            return result;
+          }
+          
+          public override bool IsInitialized {
+            get { return result.IsInitialized; }
+          }
           
           protected override Item MessageBeingBuilt {
-            get { return result; }
+            get { return PrepareBuilder(); }
           }
           
           public override Builder Clear() {
-            result = new Item();
+            result = DefaultInstance;
+            resultIsReadOnly = true;
             return this;
           }
           
           public override Builder Clone() {
-            return new Builder().MergeFrom(result);
+            if (resultIsReadOnly) {
+              return new Builder(result);
+            } else {
+              return new Builder().MergeFrom(result);
+            }
           }
           
           public override pbd::MessageDescriptor DescriptorForType {
@@ -1235,12 +1408,11 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           
           public override Item BuildPartial() {
-            if (result == null) {
-              throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+            if (resultIsReadOnly) {
+              return result;
             }
-            Item returnMe = result;
-            result = null;
-            return returnMe;
+            resultIsReadOnly = true;
+            return result.MakeReadOnly();
           }
           
           public override Builder MergeFrom(pb::IMessage other) {
@@ -1254,6 +1426,7 @@ namespace Google.ProtocolBuffers.TestProtos {
           
           public override Builder MergeFrom(Item other) {
             if (other == global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item.DefaultInstance) return this;
+            PrepareBuilder();
             if (other.HasTypeId) {
               TypeId = other.TypeId;
             }
@@ -1269,6 +1442,7 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           
           public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+            PrepareBuilder();
             pb::UnknownFieldSet.Builder unknownFields = null;
             uint tag;
             string field_name;
@@ -1328,11 +1502,13 @@ namespace Google.ProtocolBuffers.TestProtos {
             set { SetTypeId(value); }
           }
           public Builder SetTypeId(int value) {
+            PrepareBuilder();
             result.hasTypeId = true;
             result.typeId_ = value;
             return this;
           }
           public Builder ClearTypeId() {
+            PrepareBuilder();
             result.hasTypeId = false;
             result.typeId_ = 0;
             return this;
@@ -1347,11 +1523,13 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           public Builder SetMessage(pb::ByteString value) {
             pb::ThrowHelper.ThrowIfNull(value, "value");
+            PrepareBuilder();
             result.hasMessage = true;
             result.message_ = value;
             return this;
           }
           public Builder ClearMessage() {
+            PrepareBuilder();
             result.hasMessage = false;
             result.message_ = pb::ByteString.Empty;
             return this;
@@ -1438,11 +1616,16 @@ namespace Google.ProtocolBuffers.TestProtos {
     public static RawMessageSet ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
       return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
     }
+    private RawMessageSet MakeReadOnly() {
+      item_.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(RawMessageSet prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -1452,21 +1635,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(RawMessageSet cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
+      
+      private bool resultIsReadOnly;
+      private RawMessageSet result;
       
-      RawMessageSet result = new RawMessageSet();
+      private RawMessageSet PrepareBuilder() {
+        if (resultIsReadOnly) {
+          RawMessageSet original = result;
+          result = new RawMessageSet();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override RawMessageSet MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new RawMessageSet();
+        result = DefaultInstance;
+        resultIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -1478,13 +1688,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override RawMessageSet BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (resultIsReadOnly) {
+          return result;
         }
-        result.item_.MakeReadOnly();
-        RawMessageSet returnMe = result;
-        result = null;
-        return returnMe;
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -1498,8 +1706,9 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(RawMessageSet other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.RawMessageSet.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.item_.Count != 0) {
-          base.AddRange(other.item_, result.item_);
+          result.item_.Add(other.item_);
         }
         this.MergeUnknownFields(other.UnknownFields);
         return this;
@@ -1510,6 +1719,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -1558,7 +1768,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       
       public pbc::IPopsicleList<global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item> ItemList {
-        get { return result.item_; }
+        get { return PrepareBuilder().item_; }
       }
       public int ItemCount {
         get { return result.ItemCount; }
@@ -1568,29 +1778,35 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetItem(int index, global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.item_[index] = value;
         return this;
       }
       public Builder SetItem(int index, global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.item_[index] = builderForValue.Build();
         return this;
       }
       public Builder AddItem(global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.item_.Add(value);
         return this;
       }
       public Builder AddItem(global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.item_.Add(builderForValue.Build());
         return this;
       }
       public Builder AddRangeItem(scg::IEnumerable<global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item> values) {
-        base.AddRange(values, result.item_);
+        PrepareBuilder();
+        result.item_.Add(values);
         return this;
       }
       public Builder ClearItem() {
+        PrepareBuilder();
         result.item_.Clear();
         return this;
       }

+ 49 - 14
src/ProtocolBuffers.Test/TestProtos/UnitTestNoGenericServicesProtoFile.cs

@@ -1,5 +1,5 @@
 // Generated by ProtoGen, Version=2.3.0.277, Culture=neutral, PublicKeyToken=17b3b1f090c3ea48.  DO NOT EDIT!
-#pragma warning disable 1591
+#pragma warning disable 1591, 0612
 #region Designer generated code
 
 using pb = global::Google.ProtocolBuffers;
@@ -81,7 +81,8 @@ namespace Google.ProtocolBuffers.TestProtos.NoGenericService {
   [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
   [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
   public sealed partial class TestMessage : pb::ExtendableMessage<TestMessage, TestMessage.Builder> {
-    private static readonly TestMessage defaultInstance = new Builder().BuildPartial();
+    private TestMessage() { }
+    private static readonly TestMessage defaultInstance = new TestMessage().MakeReadOnly();
     private static readonly string[] _testMessageFieldNames = new string[] { "a" };
     private static readonly uint[] _testMessageFieldTags = new uint[] { 8 };
     public static TestMessage DefaultInstance {
@@ -89,7 +90,7 @@ namespace Google.ProtocolBuffers.TestProtos.NoGenericService {
     }
     
     public override TestMessage DefaultInstanceForType {
-      get { return defaultInstance; }
+      get { return DefaultInstance; }
     }
     
     protected override TestMessage ThisMessage {
@@ -179,11 +180,15 @@ namespace Google.ProtocolBuffers.TestProtos.NoGenericService {
     public static TestMessage ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
       return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
     }
+    private TestMessage 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(TestMessage prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -193,21 +198,48 @@ namespace Google.ProtocolBuffers.TestProtos.NoGenericService {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(TestMessage cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
+      
+      private bool resultIsReadOnly;
+      private TestMessage result;
+      
+      private TestMessage PrepareBuilder() {
+        if (resultIsReadOnly) {
+          TestMessage original = result;
+          result = new TestMessage();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
       
-      TestMessage result = new TestMessage();
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override TestMessage MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new TestMessage();
+        result = DefaultInstance;
+        resultIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -219,12 +251,11 @@ namespace Google.ProtocolBuffers.TestProtos.NoGenericService {
       }
       
       public override TestMessage BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (resultIsReadOnly) {
+          return result;
         }
-        TestMessage returnMe = result;
-        result = null;
-        return returnMe;
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -238,6 +269,7 @@ namespace Google.ProtocolBuffers.TestProtos.NoGenericService {
       
       public override Builder MergeFrom(TestMessage other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.NoGenericService.TestMessage.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasA) {
           A = other.A;
         }
@@ -251,6 +283,7 @@ namespace Google.ProtocolBuffers.TestProtos.NoGenericService {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -306,11 +339,13 @@ namespace Google.ProtocolBuffers.TestProtos.NoGenericService {
         set { SetA(value); }
       }
       public Builder SetA(int value) {
+        PrepareBuilder();
         result.hasA = true;
         result.a_ = value;
         return this;
       }
       public Builder ClearA() {
+        PrepareBuilder();
         result.hasA = false;
         result.a_ = 0;
         return this;

+ 151 - 46
src/ProtocolBuffers.Test/TestProtos/UnitTestOptimizeForProtoFile.cs

@@ -1,5 +1,5 @@
 // Generated by ProtoGen, Version=2.3.0.277, Culture=neutral, PublicKeyToken=17b3b1f090c3ea48.  DO NOT EDIT!
-#pragma warning disable 1591
+#pragma warning disable 1591, 0612
 #region Designer generated code
 
 using pb = global::Google.ProtocolBuffers;
@@ -85,13 +85,14 @@ namespace Google.ProtocolBuffers.TestProtos {
   [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
   [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
   public sealed partial class TestOptimizedForSize : pb::ExtendableMessage<TestOptimizedForSize, TestOptimizedForSize.Builder> {
-    private static readonly TestOptimizedForSize defaultInstance = new Builder().BuildPartial();
+    private TestOptimizedForSize() { }
+    private static readonly TestOptimizedForSize defaultInstance = new TestOptimizedForSize().MakeReadOnly();
     public static TestOptimizedForSize DefaultInstance {
       get { return defaultInstance; }
     }
     
     public override TestOptimizedForSize DefaultInstanceForType {
-      get { return defaultInstance; }
+      get { return DefaultInstance; }
     }
     
     protected override TestOptimizedForSize ThisMessage {
@@ -122,12 +123,12 @@ namespace Google.ProtocolBuffers.TestProtos {
     
     public const int MsgFieldNumber = 19;
     private bool hasMsg;
-    private global::Google.ProtocolBuffers.TestProtos.ForeignMessage msg_ = global::Google.ProtocolBuffers.TestProtos.ForeignMessage.DefaultInstance;
+    private global::Google.ProtocolBuffers.TestProtos.ForeignMessage msg_;
     public bool HasMsg {
       get { return hasMsg; }
     }
     public global::Google.ProtocolBuffers.TestProtos.ForeignMessage Msg {
-      get { return msg_; }
+      get { return msg_ ?? global::Google.ProtocolBuffers.TestProtos.ForeignMessage.DefaultInstance; }
     }
     
     public static TestOptimizedForSize ParseFrom(pb::ByteString data) {
@@ -160,11 +161,15 @@ namespace Google.ProtocolBuffers.TestProtos {
     public static TestOptimizedForSize ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
       return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
     }
+    private TestOptimizedForSize 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(TestOptimizedForSize prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -174,21 +179,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(TestOptimizedForSize cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
+      
+      private bool resultIsReadOnly;
+      private TestOptimizedForSize result;
+      
+      private TestOptimizedForSize PrepareBuilder() {
+        if (resultIsReadOnly) {
+          TestOptimizedForSize original = result;
+          result = new TestOptimizedForSize();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
       
-      TestOptimizedForSize result = new TestOptimizedForSize();
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override TestOptimizedForSize MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new TestOptimizedForSize();
+        result = DefaultInstance;
+        resultIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -200,12 +232,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override TestOptimizedForSize BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (resultIsReadOnly) {
+          return result;
         }
-        TestOptimizedForSize returnMe = result;
-        result = null;
-        return returnMe;
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
       }
       
       
@@ -217,11 +248,13 @@ namespace Google.ProtocolBuffers.TestProtos {
         set { SetI(value); }
       }
       public Builder SetI(int value) {
+        PrepareBuilder();
         result.hasI = true;
         result.i_ = value;
         return this;
       }
       public Builder ClearI() {
+        PrepareBuilder();
         result.hasI = false;
         result.i_ = 0;
         return this;
@@ -236,18 +269,21 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetMsg(global::Google.ProtocolBuffers.TestProtos.ForeignMessage value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasMsg = true;
         result.msg_ = value;
         return this;
       }
       public Builder SetMsg(global::Google.ProtocolBuffers.TestProtos.ForeignMessage.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.hasMsg = true;
         result.msg_ = builderForValue.Build();
         return this;
       }
       public Builder MergeMsg(global::Google.ProtocolBuffers.TestProtos.ForeignMessage value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         if (result.hasMsg &&
             result.msg_ != global::Google.ProtocolBuffers.TestProtos.ForeignMessage.DefaultInstance) {
             result.msg_ = global::Google.ProtocolBuffers.TestProtos.ForeignMessage.CreateBuilder(result.msg_).MergeFrom(value).BuildPartial();
@@ -258,8 +294,9 @@ namespace Google.ProtocolBuffers.TestProtos {
         return this;
       }
       public Builder ClearMsg() {
+        PrepareBuilder();
         result.hasMsg = false;
-        result.msg_ = global::Google.ProtocolBuffers.TestProtos.ForeignMessage.DefaultInstance;
+        result.msg_ = null;
         return this;
       }
     }
@@ -272,13 +309,14 @@ namespace Google.ProtocolBuffers.TestProtos {
   [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
   [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
   public sealed partial class TestRequiredOptimizedForSize : pb::GeneratedMessage<TestRequiredOptimizedForSize, TestRequiredOptimizedForSize.Builder> {
-    private static readonly TestRequiredOptimizedForSize defaultInstance = new Builder().BuildPartial();
+    private TestRequiredOptimizedForSize() { }
+    private static readonly TestRequiredOptimizedForSize defaultInstance = new TestRequiredOptimizedForSize().MakeReadOnly();
     public static TestRequiredOptimizedForSize DefaultInstance {
       get { return defaultInstance; }
     }
     
     public override TestRequiredOptimizedForSize DefaultInstanceForType {
-      get { return defaultInstance; }
+      get { return DefaultInstance; }
     }
     
     protected override TestRequiredOptimizedForSize ThisMessage {
@@ -333,11 +371,15 @@ namespace Google.ProtocolBuffers.TestProtos {
     public static TestRequiredOptimizedForSize ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
       return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
     }
+    private TestRequiredOptimizedForSize 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(TestRequiredOptimizedForSize prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -347,21 +389,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(TestRequiredOptimizedForSize cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
+      
+      private bool resultIsReadOnly;
+      private TestRequiredOptimizedForSize result;
+      
+      private TestRequiredOptimizedForSize PrepareBuilder() {
+        if (resultIsReadOnly) {
+          TestRequiredOptimizedForSize original = result;
+          result = new TestRequiredOptimizedForSize();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
       
-      TestRequiredOptimizedForSize result = new TestRequiredOptimizedForSize();
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override TestRequiredOptimizedForSize MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new TestRequiredOptimizedForSize();
+        result = DefaultInstance;
+        resultIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -373,12 +442,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override TestRequiredOptimizedForSize BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (resultIsReadOnly) {
+          return result;
         }
-        TestRequiredOptimizedForSize returnMe = result;
-        result = null;
-        return returnMe;
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
       }
       
       
@@ -390,11 +458,13 @@ namespace Google.ProtocolBuffers.TestProtos {
         set { SetX(value); }
       }
       public Builder SetX(int value) {
+        PrepareBuilder();
         result.hasX = true;
         result.x_ = value;
         return this;
       }
       public Builder ClearX() {
+        PrepareBuilder();
         result.hasX = false;
         result.x_ = 0;
         return this;
@@ -409,13 +479,14 @@ namespace Google.ProtocolBuffers.TestProtos {
   [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
   [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
   public sealed partial class TestOptionalOptimizedForSize : pb::GeneratedMessage<TestOptionalOptimizedForSize, TestOptionalOptimizedForSize.Builder> {
-    private static readonly TestOptionalOptimizedForSize defaultInstance = new Builder().BuildPartial();
+    private TestOptionalOptimizedForSize() { }
+    private static readonly TestOptionalOptimizedForSize defaultInstance = new TestOptionalOptimizedForSize().MakeReadOnly();
     public static TestOptionalOptimizedForSize DefaultInstance {
       get { return defaultInstance; }
     }
     
     public override TestOptionalOptimizedForSize DefaultInstanceForType {
-      get { return defaultInstance; }
+      get { return DefaultInstance; }
     }
     
     protected override TestOptionalOptimizedForSize ThisMessage {
@@ -432,12 +503,12 @@ namespace Google.ProtocolBuffers.TestProtos {
     
     public const int OFieldNumber = 1;
     private bool hasO;
-    private global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize o_ = global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize.DefaultInstance;
+    private global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize o_;
     public bool HasO {
       get { return hasO; }
     }
     public global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize O {
-      get { return o_; }
+      get { return o_ ?? global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize.DefaultInstance; }
     }
     
     public static TestOptionalOptimizedForSize ParseFrom(pb::ByteString data) {
@@ -470,11 +541,15 @@ namespace Google.ProtocolBuffers.TestProtos {
     public static TestOptionalOptimizedForSize ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
       return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
     }
+    private TestOptionalOptimizedForSize 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(TestOptionalOptimizedForSize prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -484,21 +559,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(TestOptionalOptimizedForSize cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
+      
+      private bool resultIsReadOnly;
+      private TestOptionalOptimizedForSize result;
       
-      TestOptionalOptimizedForSize result = new TestOptionalOptimizedForSize();
+      private TestOptionalOptimizedForSize PrepareBuilder() {
+        if (resultIsReadOnly) {
+          TestOptionalOptimizedForSize original = result;
+          result = new TestOptionalOptimizedForSize();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override TestOptionalOptimizedForSize MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new TestOptionalOptimizedForSize();
+        result = DefaultInstance;
+        resultIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -510,12 +612,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override TestOptionalOptimizedForSize BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (resultIsReadOnly) {
+          return result;
         }
-        TestOptionalOptimizedForSize returnMe = result;
-        result = null;
-        return returnMe;
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
       }
       
       
@@ -528,18 +629,21 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetO(global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasO = true;
         result.o_ = value;
         return this;
       }
       public Builder SetO(global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.hasO = true;
         result.o_ = builderForValue.Build();
         return this;
       }
       public Builder MergeO(global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         if (result.hasO &&
             result.o_ != global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize.DefaultInstance) {
             result.o_ = global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize.CreateBuilder(result.o_).MergeFrom(value).BuildPartial();
@@ -550,8 +654,9 @@ namespace Google.ProtocolBuffers.TestProtos {
         return this;
       }
       public Builder ClearO() {
+        PrepareBuilder();
         result.hasO = false;
-        result.o_ = global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize.DefaultInstance;
+        result.o_ = null;
         return this;
       }
     }

Plik diff jest za duży
+ 286 - 111
src/ProtocolBuffers.Test/TestProtos/UnitTestProtoFile.cs


+ 222 - 68
src/ProtocolBuffers.Test/TestProtos/UnitTestRpcInterop.cs

@@ -1,5 +1,5 @@
 // Generated by ProtoGen, Version=2.3.0.277, Culture=neutral, PublicKeyToken=17b3b1f090c3ea48.  DO NOT EDIT!
-#pragma warning disable 1591
+#pragma warning disable 1591, 0612
 #region Designer generated code
 
 using pb = global::Google.ProtocolBuffers;
@@ -83,7 +83,8 @@ namespace Google.ProtocolBuffers.TestProtos {
   [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();
+    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 {
@@ -91,7 +92,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     }
     
     public override SearchRequest DefaultInstanceForType {
-      get { return defaultInstance; }
+      get { return DefaultInstance; }
     }
     
     protected override SearchRequest ThisMessage {
@@ -184,11 +185,16 @@ namespace Google.ProtocolBuffers.TestProtos {
     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 (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -198,21 +204,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(SearchRequest cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
       
-      SearchRequest result = new SearchRequest();
+      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 result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new SearchRequest();
+        result = DefaultInstance;
+        resultIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -224,13 +257,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override SearchRequest BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (resultIsReadOnly) {
+          return result;
         }
-        result.criteria_.MakeReadOnly();
-        SearchRequest returnMe = result;
-        result = null;
-        return returnMe;
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -244,8 +275,9 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(SearchRequest other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.SearchRequest.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.criteria_.Count != 0) {
-          base.AddRange(other.criteria_, result.criteria_);
+          result.criteria_.Add(other.criteria_);
         }
         this.MergeUnknownFields(other.UnknownFields);
         return this;
@@ -256,6 +288,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -304,7 +337,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       
       public pbc::IPopsicleList<string> CriteriaList {
-        get { return result.criteria_; }
+        get { return PrepareBuilder().criteria_; }
       }
       public int CriteriaCount {
         get { return result.CriteriaCount; }
@@ -314,19 +347,23 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       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) {
-        base.AddRange(values, result.criteria_);
+        PrepareBuilder();
+        result.criteria_.Add(values);
         return this;
       }
       public Builder ClearCriteria() {
+        PrepareBuilder();
         result.criteria_.Clear();
         return this;
       }
@@ -340,7 +377,8 @@ namespace Google.ProtocolBuffers.TestProtos {
   [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();
+    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 {
@@ -348,7 +386,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     }
     
     public override SearchResponse DefaultInstanceForType {
-      get { return defaultInstance; }
+      get { return DefaultInstance; }
     }
     
     protected override SearchResponse ThisMessage {
@@ -372,7 +410,8 @@ namespace Google.ProtocolBuffers.TestProtos {
       [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();
+        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 {
@@ -380,7 +419,7 @@ namespace Google.ProtocolBuffers.TestProtos {
         }
         
         public override ResultItem DefaultInstanceForType {
-          get { return defaultInstance; }
+          get { return DefaultInstance; }
         }
         
         protected override ResultItem ThisMessage {
@@ -483,11 +522,15 @@ namespace Google.ProtocolBuffers.TestProtos {
         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 (Builder) new Builder().MergeFrom(prototype);
+          return new Builder(prototype);
         }
         
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -497,21 +540,48 @@ namespace Google.ProtocolBuffers.TestProtos {
           protected override Builder ThisBuilder {
             get { return this; }
           }
-          public Builder() {}
+          public Builder() {
+            result = DefaultInstance;
+            resultIsReadOnly = true;
+          }
+          internal Builder(ResultItem cloneFrom) {
+            result = cloneFrom;
+            resultIsReadOnly = true;
+          }
           
-          ResultItem result = new ResultItem();
+          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 result; }
+            get { return PrepareBuilder(); }
           }
           
           public override Builder Clear() {
-            result = new ResultItem();
+            result = DefaultInstance;
+            resultIsReadOnly = true;
             return this;
           }
           
           public override Builder Clone() {
-            return new Builder().MergeFrom(result);
+            if (resultIsReadOnly) {
+              return new Builder(result);
+            } else {
+              return new Builder().MergeFrom(result);
+            }
           }
           
           public override pbd::MessageDescriptor DescriptorForType {
@@ -523,12 +593,11 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           
           public override ResultItem BuildPartial() {
-            if (result == null) {
-              throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+            if (resultIsReadOnly) {
+              return result;
             }
-            ResultItem returnMe = result;
-            result = null;
-            return returnMe;
+            resultIsReadOnly = true;
+            return result.MakeReadOnly();
           }
           
           public override Builder MergeFrom(pb::IMessage other) {
@@ -542,6 +611,7 @@ namespace Google.ProtocolBuffers.TestProtos {
           
           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;
             }
@@ -557,6 +627,7 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           
           public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+            PrepareBuilder();
             pb::UnknownFieldSet.Builder unknownFields = null;
             uint tag;
             string field_name;
@@ -617,11 +688,13 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           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;
@@ -636,11 +709,13 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           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;
@@ -730,11 +805,16 @@ namespace Google.ProtocolBuffers.TestProtos {
     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 (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -744,21 +824,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      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;
+      }
       
-      SearchResponse result = new SearchResponse();
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override SearchResponse MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new SearchResponse();
+        result = DefaultInstance;
+        resultIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -770,13 +877,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override SearchResponse BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (resultIsReadOnly) {
+          return result;
         }
-        result.results_.MakeReadOnly();
-        SearchResponse returnMe = result;
-        result = null;
-        return returnMe;
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -790,8 +895,9 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(SearchResponse other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.SearchResponse.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.results_.Count != 0) {
-          base.AddRange(other.results_, result.results_);
+          result.results_.Add(other.results_);
         }
         this.MergeUnknownFields(other.UnknownFields);
         return this;
@@ -802,6 +908,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -850,7 +957,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       
       public pbc::IPopsicleList<global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem> ResultsList {
-        get { return result.results_; }
+        get { return PrepareBuilder().results_; }
       }
       public int ResultsCount {
         get { return result.ResultsCount; }
@@ -860,29 +967,35 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       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) {
-        base.AddRange(values, result.results_);
+        PrepareBuilder();
+        result.results_.Add(values);
         return this;
       }
       public Builder ClearResults() {
+        PrepareBuilder();
         result.results_.Clear();
         return this;
       }
@@ -896,7 +1009,8 @@ namespace Google.ProtocolBuffers.TestProtos {
   [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();
+    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 {
@@ -904,7 +1018,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     }
     
     public override RefineSearchRequest DefaultInstanceForType {
-      get { return defaultInstance; }
+      get { return DefaultInstance; }
     }
     
     protected override RefineSearchRequest ThisMessage {
@@ -933,12 +1047,12 @@ namespace Google.ProtocolBuffers.TestProtos {
     
     public const int PreviousResultsFieldNumber = 2;
     private bool hasPreviousResults;
-    private global::Google.ProtocolBuffers.TestProtos.SearchResponse previousResults_ = global::Google.ProtocolBuffers.TestProtos.SearchResponse.DefaultInstance;
+    private global::Google.ProtocolBuffers.TestProtos.SearchResponse previousResults_;
     public bool HasPreviousResults {
       get { return hasPreviousResults; }
     }
     public global::Google.ProtocolBuffers.TestProtos.SearchResponse PreviousResults {
-      get { return previousResults_; }
+      get { return previousResults_ ?? global::Google.ProtocolBuffers.TestProtos.SearchResponse.DefaultInstance; }
     }
     
     public override bool IsInitialized {
@@ -1015,11 +1129,16 @@ namespace Google.ProtocolBuffers.TestProtos {
     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 (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -1029,21 +1148,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      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;
+      }
       
-      RefineSearchRequest result = new RefineSearchRequest();
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override RefineSearchRequest MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new RefineSearchRequest();
+        result = DefaultInstance;
+        resultIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -1055,13 +1201,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override RefineSearchRequest BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (resultIsReadOnly) {
+          return result;
         }
-        result.criteria_.MakeReadOnly();
-        RefineSearchRequest returnMe = result;
-        result = null;
-        return returnMe;
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -1075,8 +1219,9 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(RefineSearchRequest other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.RefineSearchRequest.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.criteria_.Count != 0) {
-          base.AddRange(other.criteria_, result.criteria_);
+          result.criteria_.Add(other.criteria_);
         }
         if (other.HasPreviousResults) {
           MergePreviousResults(other.PreviousResults);
@@ -1090,6 +1235,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -1147,7 +1293,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       
       public pbc::IPopsicleList<string> CriteriaList {
-        get { return result.criteria_; }
+        get { return PrepareBuilder().criteria_; }
       }
       public int CriteriaCount {
         get { return result.CriteriaCount; }
@@ -1157,19 +1303,23 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       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) {
-        base.AddRange(values, result.criteria_);
+        PrepareBuilder();
+        result.criteria_.Add(values);
         return this;
       }
       public Builder ClearCriteria() {
+        PrepareBuilder();
         result.criteria_.Clear();
         return this;
       }
@@ -1183,18 +1333,21 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       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();
@@ -1205,8 +1358,9 @@ namespace Google.ProtocolBuffers.TestProtos {
         return this;
       }
       public Builder ClearPreviousResults() {
+        PrepareBuilder();
         result.hasPreviousResults = false;
-        result.previousResults_ = global::Google.ProtocolBuffers.TestProtos.SearchResponse.DefaultInstance;
+        result.previousResults_ = null;
         return this;
       }
     }

Plik diff jest za duży
+ 299 - 93
src/ProtocolBuffers.Test/TestProtos/UnitTestXmlSerializerTestProtoFile.cs


+ 84 - 0
src/ProtocolBuffers.Test/TestReaderForUrlEncoded.cs

@@ -0,0 +1,84 @@
+using System;
+using System.IO;
+using System.Text;
+using NUnit.Framework;
+using Google.ProtocolBuffers.TestProtos;
+using Google.ProtocolBuffers.Serialization.Http;
+
+namespace Google.ProtocolBuffers
+{
+    [TestFixture]
+    public class TestReaderForUrlEncoded
+    {
+        [Test]
+        public void Example_FromQueryString()
+        {
+            Uri sampleUri = new Uri("http://sample.com/Path/File.ext?text=two+three%20four&valid=true&numbers=1&numbers=2", UriKind.Absolute);
+
+            ICodedInputStream input = FormUrlEncodedReader.CreateInstance(sampleUri.Query);
+
+            TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder();
+            builder.MergeFrom(input);
+            
+            TestXmlMessage message = builder.Build();
+            Assert.AreEqual(true, message.Valid);
+            Assert.AreEqual("two three four", message.Text);
+            Assert.AreEqual(2, message.NumbersCount);
+            Assert.AreEqual(1, message.NumbersList[0]);
+            Assert.AreEqual(2, message.NumbersList[1]);
+        }
+
+        [Test]
+        public void Example_FromFormData()
+        {
+            Stream rawPost = new MemoryStream(Encoding.UTF8.GetBytes("text=two+three%20four&valid=true&numbers=1&numbers=2"), false);
+
+            ICodedInputStream input = FormUrlEncodedReader.CreateInstance(rawPost);
+
+            TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder();
+            builder.MergeFrom(input);
+
+            TestXmlMessage message = builder.Build();
+            Assert.AreEqual(true, message.Valid);
+            Assert.AreEqual("two three four", message.Text);
+            Assert.AreEqual(2, message.NumbersCount);
+            Assert.AreEqual(1, message.NumbersList[0]);
+            Assert.AreEqual(2, message.NumbersList[1]);
+        }
+
+        [Test]
+        public void TestEmptyValues()
+        {
+            ICodedInputStream input = FormUrlEncodedReader.CreateInstance("valid=true&text=&numbers=1");
+            TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder();
+            builder.MergeFrom(input);
+
+            Assert.IsTrue(builder.Valid);
+            Assert.IsTrue(builder.HasText);
+            Assert.AreEqual("", builder.Text);
+            Assert.AreEqual(1, builder.NumbersCount);
+            Assert.AreEqual(1, builder.NumbersList[0]);
+        }
+
+        [Test]
+        public void TestNoValue()
+        {
+            ICodedInputStream input = FormUrlEncodedReader.CreateInstance("valid=true&text&numbers=1");
+            TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder();
+            builder.MergeFrom(input);
+
+            Assert.IsTrue(builder.Valid);
+            Assert.IsTrue(builder.HasText);
+            Assert.AreEqual("", builder.Text);
+            Assert.AreEqual(1, builder.NumbersCount);
+            Assert.AreEqual(1, builder.NumbersList[0]);
+        }
+
+        [Test, ExpectedException(typeof(NotSupportedException))]
+        public void FormUrlEncodedReaderDoesNotSupportChildren()
+        {
+            ICodedInputStream input = FormUrlEncodedReader.CreateInstance("child=uh0");
+            TestXmlMessage.CreateBuilder().MergeFrom(input);
+        }
+    }
+}

+ 386 - 0
src/ProtocolBuffers.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);
+        }
+    }
+}

+ 86 - 0
src/ProtocolBuffers.Test/TestWriterFormatJson.cs

@@ -10,6 +10,70 @@ namespace Google.ProtocolBuffers
     [TestFixture]
     public class TestWriterFormatJson
     {
+        [Test]
+        public void Example_FromJson()
+        {
+            TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder();
+
+            builder.MergeFromJson(@"{""valid"":true}");
+            
+            TestXmlMessage message = builder.Build();
+            Assert.AreEqual(true, message.Valid);
+        }
+
+        [Test]
+        public void Example_ToJson()
+        {
+            TestXmlMessage message = 
+                TestXmlMessage.CreateBuilder()
+                .SetValid(true)
+                .Build();
+
+            string json = message.ToJson();
+
+            Assert.AreEqual(@"{""valid"":true}", json);
+        }
+
+        [Test]
+        public void Example_WriteJsonUsingICodedOutputStream()
+        {
+            TestXmlMessage message =
+                TestXmlMessage.CreateBuilder()
+                .SetValid(true)
+                .Build();
+
+            using (TextWriter output = new StringWriter())
+            {
+                ICodedOutputStream writer = JsonFormatWriter.CreateInstance(output);
+                writer.WriteMessageStart();      //manually begin the message, output is '{'
+                
+                writer.Flush();
+                Assert.AreEqual("{", output.ToString());
+
+                ICodedOutputStream stream = writer;
+                message.WriteTo(stream);    //write the message normally
+
+                writer.Flush();
+                Assert.AreEqual(@"{""valid"":true", output.ToString());
+
+                writer.WriteMessageEnd();        //manually write the end message '}'
+                Assert.AreEqual(@"{""valid"":true}", output.ToString());
+            }
+        }
+
+        [Test]
+        public void Example_ReadJsonUsingICodedInputStream()
+        {
+            TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder();
+            ICodedInputStream reader = JsonFormatReader.CreateInstance(@"{""valid"":true}");
+
+            reader.ReadMessageStart();  //manually read the begin the message '{'
+
+            builder.MergeFrom(reader);  //write the message normally
+
+            reader.ReadMessageEnd();    //manually read the end message '}'
+        }
+
         protected string Content;
         [System.Diagnostics.DebuggerNonUserCode]
         protected void FormatterAssert<TMessage>(TMessage message, params string[] expecting) where TMessage : IMessageLite
@@ -337,6 +401,28 @@ namespace Google.ProtocolBuffers
             Assert.AreEqual(3, ordinal);
             Assert.AreEqual(3, builder.TextlinesCount);
         }
+        [Test]
+        public void TestReadWriteJsonWithoutRoot()
+        {
+            TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder();
+            TestXmlMessage message = builder.SetText("abc").SetNumber(123).Build();
+
+            string Json;
+            using (StringWriter sw = new StringWriter())
+            {
+                ICodedOutputStream output = JsonFormatWriter.CreateInstance(sw);
+
+                message.WriteTo(output);
+                output.Flush();
+                Json = sw.ToString();
+            }
+            Assert.AreEqual(@"""text"":""abc"",""number"":123", Json);
+
+            ICodedInputStream input = JsonFormatReader.CreateInstance(Json);
+            TestXmlMessage copy = TestXmlMessage.CreateBuilder().MergeFrom(input).Build();
+
+            Assert.AreEqual(message, copy);
+        }
         [Test,ExpectedException(typeof(RecursionLimitExceededException))]
         public void TestRecursiveLimit()
         {

+ 119 - 2
src/ProtocolBuffers.Test/TestWriterFormatXml.cs

@@ -12,6 +12,65 @@ namespace Google.ProtocolBuffers
     [TestFixture]
     public class TestWriterFormatXml
     {
+        [Test]
+        public void Example_FromXml()
+        {
+            TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder();
+
+            XmlReader rdr = XmlReader.Create(new StringReader(@"<root><valid>true</valid></root>"));
+            builder.MergeFromXml(rdr);
+
+            TestXmlMessage message = builder.Build();
+            Assert.AreEqual(true, message.Valid);
+        }
+
+        [Test]
+        public void Example_ToXml()
+        {
+            TestXmlMessage message =
+                TestXmlMessage.CreateBuilder()
+                .SetValid(true)
+                .Build();
+
+            string Xml = message.ToXml();
+
+            Assert.AreEqual(@"<root><valid>true</valid></root>", Xml);
+        }
+
+        [Test]
+        public void Example_WriteXmlUsingICodedOutputStream()
+        {
+            TestXmlMessage message =
+                TestXmlMessage.CreateBuilder()
+                .SetValid(true)
+                .Build();
+
+            using (TextWriter output = new StringWriter())
+            {
+                ICodedOutputStream writer = XmlFormatWriter.CreateInstance(output);
+                writer.WriteMessageStart();      //manually begin the message, output is '{'
+
+                ICodedOutputStream stream = writer;
+                message.WriteTo(stream);         //write the message normally
+
+                writer.WriteMessageEnd();        //manually write the end message '}'
+                Assert.AreEqual(@"<root><valid>true</valid></root>", output.ToString());
+            }
+        }
+
+        [Test]
+        public void Example_ReadXmlUsingICodedInputStream()
+        {
+            TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder();
+            ICodedInputStream reader = XmlFormatReader.CreateInstance(@"<root><valid>true</valid></root>");
+
+            reader.ReadMessageStart();  //manually read the begin the message '{'
+
+            builder.MergeFrom(reader);  //read the message normally
+
+            reader.ReadMessageEnd();    //manually read the end message '}'
+        }
+
         [Test]
         public void TestToXmlParseFromXml()
         {
@@ -135,7 +194,9 @@ namespace Google.ProtocolBuffers
                 .Build();
 
             StringWriter sw = new StringWriter();
-            XmlFormatWriter.CreateInstance(sw).WriteMessage("root", message);
+            XmlWriter xwtr = XmlWriter.Create(sw, new XmlWriterSettings {Indent = true, IndentChars = "  "});
+
+            XmlFormatWriter.CreateInstance(xwtr).WriteMessage("root", message);
 
             string xml = sw.ToString();
 
@@ -162,7 +223,9 @@ namespace Google.ProtocolBuffers
                 .Build();
 
             StringWriter sw = new StringWriter();
-            XmlFormatWriter.CreateInstance(sw)
+            XmlWriter xwtr = XmlWriter.Create(sw, new XmlWriterSettings { Indent = true, IndentChars = "  " });
+
+            XmlFormatWriter.CreateInstance(xwtr)
                 .SetOptions(XmlWriterOptions.OutputNestedArrays | XmlWriterOptions.OutputEnumValues)
                 .WriteMessage("root", message);
 
@@ -324,6 +387,60 @@ namespace Google.ProtocolBuffers
             TestXmlMessage copy = rdr.Merge(TestXmlMessage.CreateBuilder(), registry).Build();
             Assert.AreEqual(message, copy);
         }
+        [Test]
+        public void TestXmlReadEmptyRoot()
+        {
+            TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder();
+            ICodedInputStream reader = XmlFormatReader.CreateInstance(@"<root/>");
+
+            reader.ReadMessageStart();  //manually read the begin the message '{'
+
+            builder.MergeFrom(reader);  //write the message normally
+
+            reader.ReadMessageEnd();    //manually read the end message '}'
+        }
+
+        [Test]
+        public void TestXmlReadEmptyChild()
+        {
+            TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder();
+            ICodedInputStream reader = XmlFormatReader.CreateInstance(@"<root><text /></root>");
+
+            reader.ReadMessageStart();  //manually read the begin the message '{'
+
+            builder.MergeFrom(reader);  //write the message normally
+            Assert.IsTrue(builder.HasText);
+            Assert.AreEqual(String.Empty, builder.Text);
+        }
+
+        [Test]
+        public void TestXmlReadWriteWithoutRoot()
+        {
+            TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder();
+            TestXmlMessage message = builder.SetText("abc").SetNumber(123).Build();
+
+            string xml;
+            using (StringWriter sw = new StringWriter())
+            {
+                ICodedOutputStream output = XmlFormatWriter.CreateInstance(
+                    XmlWriter.Create(sw, new XmlWriterSettings() { ConformanceLevel = ConformanceLevel.Fragment }));
+
+                message.WriteTo(output);
+                output.Flush();
+                xml = sw.ToString();
+            }
+            Assert.AreEqual("<text>abc</text><number>123</number>", xml);
+
+            TestXmlMessage copy;
+            using (XmlReader xr = XmlReader.Create(new StringReader(xml), new XmlReaderSettings() { ConformanceLevel = ConformanceLevel.Fragment }))
+            {
+                ICodedInputStream input = XmlFormatReader.CreateInstance(xr);
+                copy = TestXmlMessage.CreateBuilder().MergeFrom(input).Build();
+            }
+
+            Assert.AreEqual(message, copy);
+        }
+
         [Test, ExpectedException(typeof(RecursionLimitExceededException))]
         public void TestRecursiveLimit()
         {

+ 3 - 0
src/ProtocolBuffers/CodedInputStream.cs

@@ -144,6 +144,9 @@ namespace Google.ProtocolBuffers
 
         #endregion
 
+        void ICodedInputStream.ReadMessageStart() { }
+        void ICodedInputStream.ReadMessageEnd() { }
+
         #region Validation
 
         /// <summary>

+ 2 - 2
src/ProtocolBuffers/CodedOutputStream.ComputeSize.cs

@@ -202,7 +202,7 @@ namespace Google.ProtocolBuffers
         /// </summary>
         public static int ComputeEnumSize(int fieldNumber, int value)
         {
-            return ComputeTagSize(fieldNumber) + ComputeRawVarint32Size((uint) value);
+            return ComputeTagSize(fieldNumber) + ComputeEnumSizeNoTag(value);
         }
 
         /// <summary>
@@ -391,7 +391,7 @@ namespace Google.ProtocolBuffers
         /// </summary>
         public static int ComputeEnumSizeNoTag(int value)
         {
-            return ComputeRawVarint32Size((uint) value);
+            return ComputeInt32SizeNoTag(value);
         }
 
         /// <summary>

+ 5 - 2
src/ProtocolBuffers/CodedOutputStream.cs

@@ -125,6 +125,9 @@ namespace Google.ProtocolBuffers
         }
 
         #endregion
+        
+        void ICodedOutputStream.WriteMessageStart() { }
+        void ICodedOutputStream.WriteMessageEnd() { Flush(); }
 
         #region Writing of unknown fields
 
@@ -373,7 +376,7 @@ namespace Google.ProtocolBuffers
         public void WriteEnum(int fieldNumber, string fieldName, int value, object rawValue)
         {
             WriteTag(fieldNumber, WireFormat.WireType.Varint);
-            WriteRawVarint32((uint) value);
+            WriteInt32NoTag(value);
         }
 
         public void WriteSFixed32(int fieldNumber, string fieldName, int value)
@@ -648,7 +651,7 @@ namespace Google.ProtocolBuffers
 
         public void WriteEnumNoTag(int value)
         {
-            WriteRawVarint32((uint) value);
+            WriteInt32NoTag(value);
         }
 
         public void WriteSFixed32NoTag(int value)

+ 33 - 5
src/ProtocolBuffers/Collections/PopsicleList.cs

@@ -42,6 +42,7 @@ namespace Google.ProtocolBuffers.Collections
     /// </summary>
     public sealed class PopsicleList<T> : IPopsicleList<T>, ICastArray
     {
+        private static readonly bool CheckForNull = default(T) == null;
         private static readonly T[] EmptySet = new T[0];
 
         private List<T> items;
@@ -65,6 +66,10 @@ namespace Google.ProtocolBuffers.Collections
         public void Insert(int index, T item)
         {
             ValidateModification();
+            if (CheckForNull)
+            {
+                ThrowHelper.ThrowIfNull(item);
+            }
             items.Insert(index, item);
         }
 
@@ -87,6 +92,10 @@ namespace Google.ProtocolBuffers.Collections
             set
             {
                 ValidateModification();
+                if (CheckForNull)
+                {
+                    ThrowHelper.ThrowIfNull(value);
+                }
                 items[index] = value;
             }
         }
@@ -94,6 +103,10 @@ namespace Google.ProtocolBuffers.Collections
         public void Add(T item)
         {
             ValidateModification();
+            if (CheckForNull)
+            {
+                ThrowHelper.ThrowIfNull(item);
+            }
             items.Add(item);
         }
 
@@ -145,15 +158,30 @@ namespace Google.ProtocolBuffers.Collections
 
         public void Add(IEnumerable<T> collection)
         {
-            if (readOnly)
+            ValidateModification();
+            ThrowHelper.ThrowIfNull(collection);
+
+            if (!CheckForNull || collection is PopsicleList<T>)
             {
-                throw new NotSupportedException("List is read-only");
+                items.AddRange(collection);
             }
-            if (items == null)
+            else
             {
-                items = new List<T>();
+                // Assumption, it's ok to enumerate collections more than once.
+                if (collection is ICollection<T>)
+                {
+                    ThrowHelper.ThrowIfAnyNull(collection);
+                    items.AddRange(collection);
+                }
+                else
+                {
+                    foreach (T item in collection)
+                    {
+                        ThrowHelper.ThrowIfNull(item);
+                        items.Add(item);
+                    }
+                }
             }
-            items.AddRange(collection);
         }
 
         private void ValidateModification()

+ 12 - 10
src/ProtocolBuffers/CustomSerialization.cs

@@ -45,7 +45,7 @@ namespace Google.ProtocolBuffers
 {
     /* 
      * Specialized handing of *all* message types.  Messages are serialized into a byte[] and stored
-     * into the SerializationInfo, they are then reconstituded by an IObjectReference class after
+     * into the SerializationInfo, and are then reconstituted by an IObjectReference class after
      * deserialization.  IDeserializationCallback is supported on both the Builder and Message.
      */
     [Serializable]
@@ -71,22 +71,23 @@ namespace Google.ProtocolBuffers
                 _initialized = info.GetBoolean("initialized");
             }
 
-            Object IObjectReference.GetRealObject(StreamingContext context)
+            object IObjectReference.GetRealObject(StreamingContext context)
             {
                 ExtensionRegistry registry = context.Context as ExtensionRegistry;
                 TBuilder builder = TemplateInstance.DefaultInstanceForType.CreateBuilderForType();
                 builder.MergeFrom(_message, registry ?? ExtensionRegistry.Empty);
 
-                if (builder is IDeserializationCallback)
+                IDeserializationCallback callback = builder as IDeserializationCallback;
+                if(callback != null)
                 {
-                    ((IDeserializationCallback) builder).OnDeserialization(context);
+                    callback.OnDeserialization(context);
                 }
 
                 TMessage message = _initialized ? builder.Build() : builder.BuildPartial();
-
-                if (message is IDeserializationCallback)
+                callback = message as IDeserializationCallback;
+                if (callback != null)
                 {
-                    ((IDeserializationCallback) message).OnDeserialization(context);
+                    callback.OnDeserialization(context);
                 }
 
                 return message;
@@ -119,15 +120,16 @@ namespace Google.ProtocolBuffers
                 _message = (byte[])info.GetValue("message", typeof(byte[]));
             }
 
-            Object IObjectReference.GetRealObject(StreamingContext context)
+            object IObjectReference.GetRealObject(StreamingContext context)
             {
                 ExtensionRegistry registry = context.Context as ExtensionRegistry;
                 TBuilder builder = TemplateInstance.DefaultInstanceForType.CreateBuilderForType();
                 builder.MergeFrom(_message, registry ?? ExtensionRegistry.Empty);
 
-                if (builder is IDeserializationCallback)
+                IDeserializationCallback callback = builder as IDeserializationCallback;
+                if(callback != null)
                 {
-                    ((IDeserializationCallback) builder).OnDeserialization(context);
+                    callback.OnDeserialization(context);
                 }
 
                 return builder;

+ 219 - 53
src/ProtocolBuffers/DescriptorProtos/CSharpOptions.cs

@@ -1,5 +1,5 @@
 // Generated by ProtoGen, Version=2.3.0.277, Culture=neutral, PublicKeyToken=17b3b1f090c3ea48.  DO NOT EDIT!
-#pragma warning disable 1591
+#pragma warning disable 1591, 0612
 #region Designer generated code
 
 using pb = global::Google.ProtocolBuffers;
@@ -126,7 +126,8 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
   [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
   [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
   public sealed partial class CSharpFileOptions : pb::GeneratedMessage<CSharpFileOptions, CSharpFileOptions.Builder> {
-    private static readonly CSharpFileOptions defaultInstance = new Builder().BuildPartial();
+    private CSharpFileOptions() { }
+    private static readonly CSharpFileOptions defaultInstance = new CSharpFileOptions().MakeReadOnly();
     private static readonly string[] _cSharpFileOptionsFieldNames = new string[] { "add_serializable", "cls_compliance", "code_contracts", "expand_namespace_directories", "file_extension", "ignore_google_protobuf", "multiple_files", "namespace", "nest_classes", "output_directory", "public_classes", "service_generator_type", "umbrella_classname", "umbrella_namespace" };
     private static readonly uint[] _cSharpFileOptionsFieldTags = new uint[] { 72, 64, 48, 56, 1770, 1792, 32, 10, 40, 1786, 24, 1800, 18, 1778 };
     public static CSharpFileOptions DefaultInstance {
@@ -134,7 +135,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
     }
     
     public override CSharpFileOptions DefaultInstanceForType {
-      get { return defaultInstance; }
+      get { return DefaultInstance; }
     }
     
     protected override CSharpFileOptions ThisMessage {
@@ -428,11 +429,15 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
     public static CSharpFileOptions ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
       return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
     }
+    private CSharpFileOptions 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(CSharpFileOptions prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -442,21 +447,48 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(CSharpFileOptions cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
+      
+      private bool resultIsReadOnly;
+      private CSharpFileOptions result;
+      
+      private CSharpFileOptions PrepareBuilder() {
+        if (resultIsReadOnly) {
+          CSharpFileOptions original = result;
+          result = new CSharpFileOptions();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
       
-      CSharpFileOptions result = new CSharpFileOptions();
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override CSharpFileOptions MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new CSharpFileOptions();
+        result = DefaultInstance;
+        resultIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -468,12 +500,11 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       
       public override CSharpFileOptions BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (resultIsReadOnly) {
+          return result;
         }
-        CSharpFileOptions returnMe = result;
-        result = null;
-        return returnMe;
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -487,6 +518,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       
       public override Builder MergeFrom(CSharpFileOptions other) {
         if (other == global::Google.ProtocolBuffers.DescriptorProtos.CSharpFileOptions.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasNamespace) {
           Namespace = other.Namespace;
         }
@@ -538,6 +570,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -654,11 +687,13 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       public Builder SetNamespace(string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasNamespace = true;
         result.namespace_ = value;
         return this;
       }
       public Builder ClearNamespace() {
+        PrepareBuilder();
         result.hasNamespace = false;
         result.namespace_ = "";
         return this;
@@ -673,11 +708,13 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       public Builder SetUmbrellaClassname(string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasUmbrellaClassname = true;
         result.umbrellaClassname_ = value;
         return this;
       }
       public Builder ClearUmbrellaClassname() {
+        PrepareBuilder();
         result.hasUmbrellaClassname = false;
         result.umbrellaClassname_ = "";
         return this;
@@ -691,11 +728,13 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
         set { SetPublicClasses(value); }
       }
       public Builder SetPublicClasses(bool value) {
+        PrepareBuilder();
         result.hasPublicClasses = true;
         result.publicClasses_ = value;
         return this;
       }
       public Builder ClearPublicClasses() {
+        PrepareBuilder();
         result.hasPublicClasses = false;
         result.publicClasses_ = true;
         return this;
@@ -709,11 +748,13 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
         set { SetMultipleFiles(value); }
       }
       public Builder SetMultipleFiles(bool value) {
+        PrepareBuilder();
         result.hasMultipleFiles = true;
         result.multipleFiles_ = value;
         return this;
       }
       public Builder ClearMultipleFiles() {
+        PrepareBuilder();
         result.hasMultipleFiles = false;
         result.multipleFiles_ = false;
         return this;
@@ -727,11 +768,13 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
         set { SetNestClasses(value); }
       }
       public Builder SetNestClasses(bool value) {
+        PrepareBuilder();
         result.hasNestClasses = true;
         result.nestClasses_ = value;
         return this;
       }
       public Builder ClearNestClasses() {
+        PrepareBuilder();
         result.hasNestClasses = false;
         result.nestClasses_ = false;
         return this;
@@ -745,11 +788,13 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
         set { SetCodeContracts(value); }
       }
       public Builder SetCodeContracts(bool value) {
+        PrepareBuilder();
         result.hasCodeContracts = true;
         result.codeContracts_ = value;
         return this;
       }
       public Builder ClearCodeContracts() {
+        PrepareBuilder();
         result.hasCodeContracts = false;
         result.codeContracts_ = false;
         return this;
@@ -763,11 +808,13 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
         set { SetExpandNamespaceDirectories(value); }
       }
       public Builder SetExpandNamespaceDirectories(bool value) {
+        PrepareBuilder();
         result.hasExpandNamespaceDirectories = true;
         result.expandNamespaceDirectories_ = value;
         return this;
       }
       public Builder ClearExpandNamespaceDirectories() {
+        PrepareBuilder();
         result.hasExpandNamespaceDirectories = false;
         result.expandNamespaceDirectories_ = false;
         return this;
@@ -781,11 +828,13 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
         set { SetClsCompliance(value); }
       }
       public Builder SetClsCompliance(bool value) {
+        PrepareBuilder();
         result.hasClsCompliance = true;
         result.clsCompliance_ = value;
         return this;
       }
       public Builder ClearClsCompliance() {
+        PrepareBuilder();
         result.hasClsCompliance = false;
         result.clsCompliance_ = true;
         return this;
@@ -799,11 +848,13 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
         set { SetAddSerializable(value); }
       }
       public Builder SetAddSerializable(bool value) {
+        PrepareBuilder();
         result.hasAddSerializable = true;
         result.addSerializable_ = value;
         return this;
       }
       public Builder ClearAddSerializable() {
+        PrepareBuilder();
         result.hasAddSerializable = false;
         result.addSerializable_ = false;
         return this;
@@ -818,11 +869,13 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       public Builder SetFileExtension(string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasFileExtension = true;
         result.fileExtension_ = value;
         return this;
       }
       public Builder ClearFileExtension() {
+        PrepareBuilder();
         result.hasFileExtension = false;
         result.fileExtension_ = ".cs";
         return this;
@@ -837,11 +890,13 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       public Builder SetUmbrellaNamespace(string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasUmbrellaNamespace = true;
         result.umbrellaNamespace_ = value;
         return this;
       }
       public Builder ClearUmbrellaNamespace() {
+        PrepareBuilder();
         result.hasUmbrellaNamespace = false;
         result.umbrellaNamespace_ = "";
         return this;
@@ -856,11 +911,13 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       public Builder SetOutputDirectory(string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasOutputDirectory = true;
         result.outputDirectory_ = value;
         return this;
       }
       public Builder ClearOutputDirectory() {
+        PrepareBuilder();
         result.hasOutputDirectory = false;
         result.outputDirectory_ = ".";
         return this;
@@ -874,11 +931,13 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
         set { SetIgnoreGoogleProtobuf(value); }
       }
       public Builder SetIgnoreGoogleProtobuf(bool value) {
+        PrepareBuilder();
         result.hasIgnoreGoogleProtobuf = true;
         result.ignoreGoogleProtobuf_ = value;
         return this;
       }
       public Builder ClearIgnoreGoogleProtobuf() {
+        PrepareBuilder();
         result.hasIgnoreGoogleProtobuf = false;
         result.ignoreGoogleProtobuf_ = false;
         return this;
@@ -892,11 +951,13 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
         set { SetServiceGeneratorType(value); }
       }
       public Builder SetServiceGeneratorType(global::Google.ProtocolBuffers.DescriptorProtos.CSharpServiceType value) {
+        PrepareBuilder();
         result.hasServiceGeneratorType = true;
         result.serviceGeneratorType_ = value;
         return this;
       }
       public Builder ClearServiceGeneratorType() {
+        PrepareBuilder();
         result.hasServiceGeneratorType = false;
         result.serviceGeneratorType_ = global::Google.ProtocolBuffers.DescriptorProtos.CSharpServiceType.NONE;
         return this;
@@ -911,7 +972,8 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
   [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
   [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
   public sealed partial class CSharpFieldOptions : pb::GeneratedMessage<CSharpFieldOptions, CSharpFieldOptions.Builder> {
-    private static readonly CSharpFieldOptions defaultInstance = new Builder().BuildPartial();
+    private CSharpFieldOptions() { }
+    private static readonly CSharpFieldOptions defaultInstance = new CSharpFieldOptions().MakeReadOnly();
     private static readonly string[] _cSharpFieldOptionsFieldNames = new string[] { "property_name" };
     private static readonly uint[] _cSharpFieldOptionsFieldTags = new uint[] { 10 };
     public static CSharpFieldOptions DefaultInstance {
@@ -919,7 +981,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
     }
     
     public override CSharpFieldOptions DefaultInstanceForType {
-      get { return defaultInstance; }
+      get { return DefaultInstance; }
     }
     
     protected override CSharpFieldOptions ThisMessage {
@@ -1005,11 +1067,15 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
     public static CSharpFieldOptions ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
       return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
     }
+    private CSharpFieldOptions 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(CSharpFieldOptions prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -1019,21 +1085,48 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(CSharpFieldOptions cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
+      
+      private bool resultIsReadOnly;
+      private CSharpFieldOptions result;
+      
+      private CSharpFieldOptions PrepareBuilder() {
+        if (resultIsReadOnly) {
+          CSharpFieldOptions original = result;
+          result = new CSharpFieldOptions();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
       
-      CSharpFieldOptions result = new CSharpFieldOptions();
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override CSharpFieldOptions MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new CSharpFieldOptions();
+        result = DefaultInstance;
+        resultIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -1045,12 +1138,11 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       
       public override CSharpFieldOptions BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (resultIsReadOnly) {
+          return result;
         }
-        CSharpFieldOptions returnMe = result;
-        result = null;
-        return returnMe;
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -1064,6 +1156,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       
       public override Builder MergeFrom(CSharpFieldOptions other) {
         if (other == global::Google.ProtocolBuffers.DescriptorProtos.CSharpFieldOptions.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasPropertyName) {
           PropertyName = other.PropertyName;
         }
@@ -1076,6 +1169,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -1132,11 +1226,13 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       public Builder SetPropertyName(string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasPropertyName = true;
         result.propertyName_ = value;
         return this;
       }
       public Builder ClearPropertyName() {
+        PrepareBuilder();
         result.hasPropertyName = false;
         result.propertyName_ = "";
         return this;
@@ -1151,7 +1247,8 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
   [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
   [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
   public sealed partial class CSharpServiceOptions : pb::GeneratedMessage<CSharpServiceOptions, CSharpServiceOptions.Builder> {
-    private static readonly CSharpServiceOptions defaultInstance = new Builder().BuildPartial();
+    private CSharpServiceOptions() { }
+    private static readonly CSharpServiceOptions defaultInstance = new CSharpServiceOptions().MakeReadOnly();
     private static readonly string[] _cSharpServiceOptionsFieldNames = new string[] { "interface_id" };
     private static readonly uint[] _cSharpServiceOptionsFieldTags = new uint[] { 10 };
     public static CSharpServiceOptions DefaultInstance {
@@ -1159,7 +1256,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
     }
     
     public override CSharpServiceOptions DefaultInstanceForType {
-      get { return defaultInstance; }
+      get { return DefaultInstance; }
     }
     
     protected override CSharpServiceOptions ThisMessage {
@@ -1245,11 +1342,15 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
     public static CSharpServiceOptions ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
       return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
     }
+    private CSharpServiceOptions 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(CSharpServiceOptions prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -1259,21 +1360,48 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(CSharpServiceOptions cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
+      
+      private bool resultIsReadOnly;
+      private CSharpServiceOptions result;
+      
+      private CSharpServiceOptions PrepareBuilder() {
+        if (resultIsReadOnly) {
+          CSharpServiceOptions original = result;
+          result = new CSharpServiceOptions();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
       
-      CSharpServiceOptions result = new CSharpServiceOptions();
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override CSharpServiceOptions MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new CSharpServiceOptions();
+        result = DefaultInstance;
+        resultIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -1285,12 +1413,11 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       
       public override CSharpServiceOptions BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (resultIsReadOnly) {
+          return result;
         }
-        CSharpServiceOptions returnMe = result;
-        result = null;
-        return returnMe;
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -1304,6 +1431,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       
       public override Builder MergeFrom(CSharpServiceOptions other) {
         if (other == global::Google.ProtocolBuffers.DescriptorProtos.CSharpServiceOptions.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasInterfaceId) {
           InterfaceId = other.InterfaceId;
         }
@@ -1316,6 +1444,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -1372,11 +1501,13 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       public Builder SetInterfaceId(string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasInterfaceId = true;
         result.interfaceId_ = value;
         return this;
       }
       public Builder ClearInterfaceId() {
+        PrepareBuilder();
         result.hasInterfaceId = false;
         result.interfaceId_ = "";
         return this;
@@ -1391,7 +1522,8 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
   [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
   [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
   public sealed partial class CSharpMethodOptions : pb::GeneratedMessage<CSharpMethodOptions, CSharpMethodOptions.Builder> {
-    private static readonly CSharpMethodOptions defaultInstance = new Builder().BuildPartial();
+    private CSharpMethodOptions() { }
+    private static readonly CSharpMethodOptions defaultInstance = new CSharpMethodOptions().MakeReadOnly();
     private static readonly string[] _cSharpMethodOptionsFieldNames = new string[] { "dispatch_id" };
     private static readonly uint[] _cSharpMethodOptionsFieldTags = new uint[] { 8 };
     public static CSharpMethodOptions DefaultInstance {
@@ -1399,7 +1531,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
     }
     
     public override CSharpMethodOptions DefaultInstanceForType {
-      get { return defaultInstance; }
+      get { return DefaultInstance; }
     }
     
     protected override CSharpMethodOptions ThisMessage {
@@ -1485,11 +1617,15 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
     public static CSharpMethodOptions ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
       return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
     }
+    private CSharpMethodOptions 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(CSharpMethodOptions prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -1499,21 +1635,48 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(CSharpMethodOptions cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
+      
+      private bool resultIsReadOnly;
+      private CSharpMethodOptions result;
+      
+      private CSharpMethodOptions PrepareBuilder() {
+        if (resultIsReadOnly) {
+          CSharpMethodOptions original = result;
+          result = new CSharpMethodOptions();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
       
-      CSharpMethodOptions result = new CSharpMethodOptions();
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override CSharpMethodOptions MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new CSharpMethodOptions();
+        result = DefaultInstance;
+        resultIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -1525,12 +1688,11 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       
       public override CSharpMethodOptions BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (resultIsReadOnly) {
+          return result;
         }
-        CSharpMethodOptions returnMe = result;
-        result = null;
-        return returnMe;
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -1544,6 +1706,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       
       public override Builder MergeFrom(CSharpMethodOptions other) {
         if (other == global::Google.ProtocolBuffers.DescriptorProtos.CSharpMethodOptions.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasDispatchId) {
           DispatchId = other.DispatchId;
         }
@@ -1556,6 +1719,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -1611,11 +1775,13 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
         set { SetDispatchId(value); }
       }
       public Builder SetDispatchId(int value) {
+        PrepareBuilder();
         result.hasDispatchId = true;
         result.dispatchId_ = value;
         return this;
       }
       public Builder ClearDispatchId() {
+        PrepareBuilder();
         result.hasDispatchId = false;
         result.dispatchId_ = 0;
         return this;

Plik diff jest za duży
+ 281 - 95
src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs


+ 3 - 34
src/ProtocolBuffers/GeneratedBuilder.cs

@@ -58,12 +58,7 @@ namespace Google.ProtocolBuffers
 
         protected internal FieldAccessorTable<TMessage, TBuilder> InternalFieldAccessors
         {
-            get { return MessageBeingBuilt.FieldAccessorsFromBuilder; }
-        }
-
-        public override bool IsInitialized
-        {
-            get { return MessageBeingBuilt.IsInitialized; }
+            get { return DefaultInstanceForType.FieldAccessorsFromBuilder; }
         }
 
         public override IDictionary<FieldDescriptor, object> AllFields
@@ -84,32 +79,6 @@ namespace Google.ProtocolBuffers
             set { InternalFieldAccessors[field].SetValue(ThisBuilder, value); }
         }
 
-        /// <summary>
-        /// Adds all of the specified values to the given collection.
-        /// </summary>
-        /// <exception cref="ArgumentNullException">Any element of the list is null</exception>
-        protected void AddRange<T>(IEnumerable<T> source, IList<T> destination)
-        {
-            ThrowHelper.ThrowIfNull(source);
-            // We only need to check this for nullable types.
-            if (default(T) == null)
-            {
-                ThrowHelper.ThrowIfAnyNull(source);
-            }
-            List<T> list = destination as List<T>;
-            if (list != null)
-            {
-                list.AddRange(source);
-            }
-            else
-            {
-                foreach (T element in source)
-                {
-                    destination.Add(element);
-                }
-            }
-        }
-
         /// <summary>
         /// Called by derived classes to parse an unknown field.
         /// </summary>
@@ -123,7 +92,7 @@ namespace Google.ProtocolBuffers
 
         public override MessageDescriptor DescriptorForType
         {
-            get { return MessageBeingBuilt.DescriptorForType; }
+            get { return DefaultInstanceForType.DescriptorForType; }
         }
 
         public override int GetRepeatedFieldCount(FieldDescriptor field)
@@ -230,7 +199,7 @@ namespace Google.ProtocolBuffers
         public override TMessage Build()
         {
             // If the message is null, we'll throw a more appropriate exception in BuildPartial.
-            if (MessageBeingBuilt != null && !IsInitialized)
+            if (!IsInitialized)
             {
                 throw new UninitializedMessageException(MessageBeingBuilt);
             }

+ 1 - 32
src/ProtocolBuffers/GeneratedBuilderLite.cs

@@ -61,37 +61,6 @@ namespace Google.ProtocolBuffers
 
         public abstract TBuilder MergeFrom(TMessage other);
 
-        public override bool IsInitialized
-        {
-            get { return MessageBeingBuilt.IsInitialized; }
-        }
-
-        /// <summary>
-        /// Adds all of the specified values to the given collection.
-        /// </summary>
-        /// <exception cref="ArgumentNullException">Any element of the list is null</exception>
-        protected void AddRange<T>(IEnumerable<T> source, IList<T> destination)
-        {
-            ThrowHelper.ThrowIfNull(source);
-            // We only need to check this for nullable types.
-            if (default(T) == null)
-            {
-                ThrowHelper.ThrowIfAnyNull(source);
-            }
-            List<T> list = destination as List<T>;
-            if (list != null)
-            {
-                list.AddRange(source);
-            }
-            else
-            {
-                foreach (T element in source)
-                {
-                    destination.Add(element);
-                }
-            }
-        }
-
         /// <summary>
         /// Called by derived classes to parse an unknown field.
         /// </summary>
@@ -122,7 +91,7 @@ namespace Google.ProtocolBuffers
         public override TMessage Build()
         {
             // If the message is null, we'll throw a more appropriate exception in BuildPartial.
-            if (MessageBeingBuilt != null && !IsInitialized)
+            if (!IsInitialized)
             {
                 throw new UninitializedMessageException(MessageBeingBuilt);
             }

+ 18 - 0
src/ProtocolBuffers/ICodedInputStream.cs

@@ -45,6 +45,24 @@ namespace Google.ProtocolBuffers
 {
     public interface ICodedInputStream
     {
+        /// <summary>
+        /// Reads any message initialization data expected from the input stream
+        /// </summary>
+        /// <remarks>
+        /// This is primarily used by text formats and unnecessary for protobuffers' own
+        /// binary format.  The API for MessageStart/End was added for consistent handling
+        /// of output streams regardless of the actual writer implementation.
+        /// </remarks>
+        void ReadMessageStart();
+        /// <summary>
+        /// Reads any message finalization data expected from the input stream
+        /// </summary>
+        /// <remarks>
+        /// This is primarily used by text formats and unnecessary for protobuffers' own
+        /// binary format.  The API for MessageStart/End was added for consistent handling
+        /// of output streams regardless of the actual writer implementation.
+        /// </remarks>
+        void ReadMessageEnd();
         /// <summary>
         /// Attempt to read a field tag, returning false if we have reached the end
         /// of the input data.

+ 18 - 0
src/ProtocolBuffers/ICodedOutputStream.cs

@@ -51,6 +51,24 @@ namespace Google.ProtocolBuffers
     /// </summary>
     public interface ICodedOutputStream
     {
+        /// <summary>
+        /// Writes any message initialization data needed to the output stream
+        /// </summary>
+        /// <remarks>
+        /// This is primarily used by text formats and unnecessary for protobuffers' own
+        /// binary format.  The API for MessageStart/End was added for consistent handling
+        /// of output streams regardless of the actual writer implementation.
+        /// </remarks>
+        void WriteMessageStart();
+        /// <summary>
+        /// Writes any message finalization data needed to the output stream
+        /// </summary>
+        /// <remarks>
+        /// This is primarily used by text formats and unnecessary for protobuffers' own
+        /// binary format.  The API for MessageStart/End was added for consistent handling
+        /// of output streams regardless of the actual writer implementation.
+        /// </remarks>
+        void WriteMessageEnd();
         /// <summary>
         /// Indicates that all temporary buffers be written to the final output.
         /// </summary>

+ 1 - 1
src/ProtocolBuffers/IRpcController.cs

@@ -105,7 +105,7 @@ namespace Google.ProtocolBuffers
         /// well give up on replying to it. This method must be called on the server
         /// side only. The server should still call the final "done" callback.
         /// </summary>
-        bool isCanceled();
+        bool IsCanceled();
 
         /// <summary>
         /// Requests that the given callback be called when the RPC is canceled.

+ 26 - 2
src/ProtocolBuffers/IRpcDispatch.cs

@@ -34,18 +34,42 @@
 
 #endregion
 
+using System;
+
 namespace Google.ProtocolBuffers
 {
     /// <summary>
-    /// 
+    /// Provides an entry-point for transport listeners to call a specified method on a service
     /// </summary>
-    public interface IRpcServerStub
+    public interface IRpcServerStub : IDisposable
     {
+        /// <summary>
+        /// Calls the method identified by methodName and returns the message
+        /// </summary>
+        /// <param name="methodName">The method name on the service descriptor (case-sensitive)</param>
+        /// <param name="input">The ICodedInputStream to deserialize the call parameter from</param>
+        /// <param name="registry">The extension registry to use when deserializing the call parameter</param>
+        /// <returns>The message that was returned from the service's method</returns>
         IMessageLite CallMethod(string methodName, ICodedInputStream input, ExtensionRegistry registry);
     }
 
+    /// <summary>
+    /// Used to forward an invocation of a service method to a transport sender implementation
+    /// </summary>
     public interface IRpcDispatch
     {
+        /// <summary>
+        /// Calls the service member on the endpoint connected.  This is generally done by serializing
+        /// the message, sending the bytes over a transport, and then deserializing the call parameter
+        /// to invoke the service's actual implementation via IRpcServerStub.  Once the call has
+        /// completed the result message is serialized and returned to the originating endpoint.
+        /// </summary>
+        /// <typeparam name="TMessage">The type of the response message</typeparam>
+        /// <typeparam name="TBuilder">The type of of the response builder</typeparam>
+        /// <param name="method">The name of the method on the service</param>
+        /// <param name="request">The message instance provided to the service call</param>
+        /// <param name="response">The builder used to deserialize the response</param>
+        /// <returns>The resulting message of the service call</returns>
         TMessage CallMethod<TMessage, TBuilder>(string method, IMessageLite request,
                                                 IBuilderLite<TMessage, TBuilder> response)
             where TMessage : IMessageLite<TMessage, TBuilder>

Plik diff jest za duży
+ 327 - 93
src/ProtocolBuffersLite.Test/TestProtos/UnitTestExtrasFullProtoFile.cs


+ 285 - 78
src/ProtocolBuffersLite.Test/TestProtos/UnitTestExtrasLiteProtoFile.cs

@@ -1,5 +1,5 @@
 // Generated by ProtoGen, Version=2.3.0.277, Culture=neutral, PublicKeyToken=17b3b1f090c3ea48.  DO NOT EDIT!
-#pragma warning disable 1591
+#pragma warning disable 1591, 0612
 #region Designer generated code
 
 using pb = global::Google.ProtocolBuffers;
@@ -60,7 +60,8 @@ namespace Google.ProtocolBuffers.TestProtos {
   [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
   [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
   public sealed partial class TestRequiredLite : pb::GeneratedMessageLite<TestRequiredLite, TestRequiredLite.Builder> {
-    private static readonly TestRequiredLite defaultInstance = new Builder().BuildPartial();
+    private TestRequiredLite() { }
+    private static readonly TestRequiredLite defaultInstance = new TestRequiredLite().MakeReadOnly();
     private static readonly string[] _testRequiredLiteFieldNames = new string[] { "d", "en" };
     private static readonly uint[] _testRequiredLiteFieldTags = new uint[] { 8, 16 };
     public static TestRequiredLite DefaultInstance {
@@ -68,7 +69,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     }
     
     public override TestRequiredLite DefaultInstanceForType {
-      get { return defaultInstance; }
+      get { return DefaultInstance; }
     }
     
     protected override TestRequiredLite ThisMessage {
@@ -184,11 +185,15 @@ namespace Google.ProtocolBuffers.TestProtos {
     public static TestRequiredLite ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
       return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
     }
+    private TestRequiredLite 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(TestRequiredLite prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.SerializableAttribute()]
@@ -199,21 +204,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(TestRequiredLite cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
+      
+      private bool resultIsReadOnly;
+      private TestRequiredLite result;
+      
+      private TestRequiredLite PrepareBuilder() {
+        if (resultIsReadOnly) {
+          TestRequiredLite original = result;
+          result = new TestRequiredLite();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
       
-      TestRequiredLite result = new TestRequiredLite();
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override TestRequiredLite MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new TestRequiredLite();
+        result = DefaultInstance;
+        resultIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override TestRequiredLite DefaultInstanceForType {
@@ -221,12 +253,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override TestRequiredLite BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (resultIsReadOnly) {
+          return result;
         }
-        TestRequiredLite returnMe = result;
-        result = null;
-        return returnMe;
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
       }
       
       public override Builder MergeFrom(pb::IMessageLite other) {
@@ -240,6 +271,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(TestRequiredLite other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.TestRequiredLite.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasD) {
           D = other.D;
         }
@@ -254,6 +286,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         uint tag;
         string field_name;
         while (input.ReadTag(out tag, out field_name)) {
@@ -304,11 +337,13 @@ namespace Google.ProtocolBuffers.TestProtos {
         set { SetD(value); }
       }
       public Builder SetD(int value) {
+        PrepareBuilder();
         result.hasD = true;
         result.d_ = value;
         return this;
       }
       public Builder ClearD() {
+        PrepareBuilder();
         result.hasD = false;
         result.d_ = 0;
         return this;
@@ -322,11 +357,13 @@ namespace Google.ProtocolBuffers.TestProtos {
         set { SetEn(value); }
       }
       public Builder SetEn(global::Google.ProtocolBuffers.TestProtos.ExtraEnum value) {
+        PrepareBuilder();
         result.hasEn = true;
         result.en_ = value;
         return this;
       }
       public Builder ClearEn() {
+        PrepareBuilder();
         result.hasEn = false;
         result.en_ = global::Google.ProtocolBuffers.TestProtos.ExtraEnum.DEFAULT;
         return this;
@@ -342,7 +379,8 @@ namespace Google.ProtocolBuffers.TestProtos {
   [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
   [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
   public sealed partial class TestInteropPersonLite : pb::ExtendableMessageLite<TestInteropPersonLite, TestInteropPersonLite.Builder> {
-    private static readonly TestInteropPersonLite defaultInstance = new Builder().BuildPartial();
+    private TestInteropPersonLite() { }
+    private static readonly TestInteropPersonLite defaultInstance = new TestInteropPersonLite().MakeReadOnly();
     private static readonly string[] _testInteropPersonLiteFieldNames = new string[] { "addresses", "codes", "email", "id", "name", "phone" };
     private static readonly uint[] _testInteropPersonLiteFieldTags = new uint[] { 43, 82, 26, 16, 10, 34 };
     public static TestInteropPersonLite DefaultInstance {
@@ -350,7 +388,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     }
     
     public override TestInteropPersonLite DefaultInstanceForType {
-      get { return defaultInstance; }
+      get { return DefaultInstance; }
     }
     
     protected override TestInteropPersonLite ThisMessage {
@@ -375,7 +413,8 @@ namespace Google.ProtocolBuffers.TestProtos {
       [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
       [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
       public sealed partial class PhoneNumber : pb::GeneratedMessageLite<PhoneNumber, PhoneNumber.Builder> {
-        private static readonly PhoneNumber defaultInstance = new Builder().BuildPartial();
+        private PhoneNumber() { }
+        private static readonly PhoneNumber defaultInstance = new PhoneNumber().MakeReadOnly();
         private static readonly string[] _phoneNumberFieldNames = new string[] { "number", "type" };
         private static readonly uint[] _phoneNumberFieldTags = new uint[] { 10, 16 };
         public static PhoneNumber DefaultInstance {
@@ -383,7 +422,7 @@ namespace Google.ProtocolBuffers.TestProtos {
         }
         
         public override PhoneNumber DefaultInstanceForType {
-          get { return defaultInstance; }
+          get { return DefaultInstance; }
         }
         
         protected override PhoneNumber ThisMessage {
@@ -498,11 +537,15 @@ namespace Google.ProtocolBuffers.TestProtos {
         public static PhoneNumber ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
           return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
         }
+        private PhoneNumber 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(PhoneNumber prototype) {
-          return (Builder) new Builder().MergeFrom(prototype);
+          return new Builder(prototype);
         }
         
         [global::System.SerializableAttribute()]
@@ -513,21 +556,48 @@ namespace Google.ProtocolBuffers.TestProtos {
           protected override Builder ThisBuilder {
             get { return this; }
           }
-          public Builder() {}
+          public Builder() {
+            result = DefaultInstance;
+            resultIsReadOnly = true;
+          }
+          internal Builder(PhoneNumber cloneFrom) {
+            result = cloneFrom;
+            resultIsReadOnly = true;
+          }
+          
+          private bool resultIsReadOnly;
+          private PhoneNumber result;
+          
+          private PhoneNumber PrepareBuilder() {
+            if (resultIsReadOnly) {
+              PhoneNumber original = result;
+              result = new PhoneNumber();
+              resultIsReadOnly = false;
+              MergeFrom(original);
+            }
+            return result;
+          }
           
-          PhoneNumber result = new PhoneNumber();
+          public override bool IsInitialized {
+            get { return result.IsInitialized; }
+          }
           
           protected override PhoneNumber MessageBeingBuilt {
-            get { return result; }
+            get { return PrepareBuilder(); }
           }
           
           public override Builder Clear() {
-            result = new PhoneNumber();
+            result = DefaultInstance;
+            resultIsReadOnly = true;
             return this;
           }
           
           public override Builder Clone() {
-            return new Builder().MergeFrom(result);
+            if (resultIsReadOnly) {
+              return new Builder(result);
+            } else {
+              return new Builder().MergeFrom(result);
+            }
           }
           
           public override PhoneNumber DefaultInstanceForType {
@@ -535,12 +605,11 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           
           public override PhoneNumber BuildPartial() {
-            if (result == null) {
-              throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+            if (resultIsReadOnly) {
+              return result;
             }
-            PhoneNumber returnMe = result;
-            result = null;
-            return returnMe;
+            resultIsReadOnly = true;
+            return result.MakeReadOnly();
           }
           
           public override Builder MergeFrom(pb::IMessageLite other) {
@@ -554,6 +623,7 @@ namespace Google.ProtocolBuffers.TestProtos {
           
           public override Builder MergeFrom(PhoneNumber other) {
             if (other == global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber.DefaultInstance) return this;
+            PrepareBuilder();
             if (other.HasNumber) {
               Number = other.Number;
             }
@@ -568,6 +638,7 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           
           public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+            PrepareBuilder();
             uint tag;
             string field_name;
             while (input.ReadTag(out tag, out field_name)) {
@@ -619,11 +690,13 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           public Builder SetNumber(string value) {
             pb::ThrowHelper.ThrowIfNull(value, "value");
+            PrepareBuilder();
             result.hasNumber = true;
             result.number_ = value;
             return this;
           }
           public Builder ClearNumber() {
+            PrepareBuilder();
             result.hasNumber = false;
             result.number_ = "";
             return this;
@@ -637,11 +710,13 @@ namespace Google.ProtocolBuffers.TestProtos {
             set { SetType(value); }
           }
           public Builder SetType(global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneType value) {
+            PrepareBuilder();
             result.hasType = true;
             result.type_ = value;
             return this;
           }
           public Builder ClearType() {
+            PrepareBuilder();
             result.hasType = false;
             result.type_ = global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneType.HOME;
             return this;
@@ -657,7 +732,8 @@ namespace Google.ProtocolBuffers.TestProtos {
       [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
       [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
       public sealed partial class Addresses : pb::GeneratedMessageLite<Addresses, Addresses.Builder> {
-        private static readonly Addresses defaultInstance = new Builder().BuildPartial();
+        private Addresses() { }
+        private static readonly Addresses defaultInstance = new Addresses().MakeReadOnly();
         private static readonly string[] _addressesFieldNames = new string[] { "address", "address2", "city", "state", "zip" };
         private static readonly uint[] _addressesFieldTags = new uint[] { 10, 18, 26, 34, 45 };
         public static Addresses DefaultInstance {
@@ -665,7 +741,7 @@ namespace Google.ProtocolBuffers.TestProtos {
         }
         
         public override Addresses DefaultInstanceForType {
-          get { return defaultInstance; }
+          get { return DefaultInstance; }
         }
         
         protected override Addresses ThisMessage {
@@ -841,11 +917,15 @@ namespace Google.ProtocolBuffers.TestProtos {
         public static Addresses ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
           return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
         }
+        private Addresses 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(Addresses prototype) {
-          return (Builder) new Builder().MergeFrom(prototype);
+          return new Builder(prototype);
         }
         
         [global::System.SerializableAttribute()]
@@ -856,21 +936,48 @@ namespace Google.ProtocolBuffers.TestProtos {
           protected override Builder ThisBuilder {
             get { return this; }
           }
-          public Builder() {}
+          public Builder() {
+            result = DefaultInstance;
+            resultIsReadOnly = true;
+          }
+          internal Builder(Addresses cloneFrom) {
+            result = cloneFrom;
+            resultIsReadOnly = true;
+          }
+          
+          private bool resultIsReadOnly;
+          private Addresses result;
+          
+          private Addresses PrepareBuilder() {
+            if (resultIsReadOnly) {
+              Addresses original = result;
+              result = new Addresses();
+              resultIsReadOnly = false;
+              MergeFrom(original);
+            }
+            return result;
+          }
           
-          Addresses result = new Addresses();
+          public override bool IsInitialized {
+            get { return result.IsInitialized; }
+          }
           
           protected override Addresses MessageBeingBuilt {
-            get { return result; }
+            get { return PrepareBuilder(); }
           }
           
           public override Builder Clear() {
-            result = new Addresses();
+            result = DefaultInstance;
+            resultIsReadOnly = true;
             return this;
           }
           
           public override Builder Clone() {
-            return new Builder().MergeFrom(result);
+            if (resultIsReadOnly) {
+              return new Builder(result);
+            } else {
+              return new Builder().MergeFrom(result);
+            }
           }
           
           public override Addresses DefaultInstanceForType {
@@ -878,12 +985,11 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           
           public override Addresses BuildPartial() {
-            if (result == null) {
-              throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+            if (resultIsReadOnly) {
+              return result;
             }
-            Addresses returnMe = result;
-            result = null;
-            return returnMe;
+            resultIsReadOnly = true;
+            return result.MakeReadOnly();
           }
           
           public override Builder MergeFrom(pb::IMessageLite other) {
@@ -897,6 +1003,7 @@ namespace Google.ProtocolBuffers.TestProtos {
           
           public override Builder MergeFrom(Addresses other) {
             if (other == global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses.DefaultInstance) return this;
+            PrepareBuilder();
             if (other.HasAddress) {
               Address = other.Address;
             }
@@ -920,6 +1027,7 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           
           public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+            PrepareBuilder();
             uint tag;
             string field_name;
             while (input.ReadTag(out tag, out field_name)) {
@@ -979,11 +1087,13 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           public Builder SetAddress(string value) {
             pb::ThrowHelper.ThrowIfNull(value, "value");
+            PrepareBuilder();
             result.hasAddress = true;
             result.address_ = value;
             return this;
           }
           public Builder ClearAddress() {
+            PrepareBuilder();
             result.hasAddress = false;
             result.address_ = "";
             return this;
@@ -998,11 +1108,13 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           public Builder SetAddress2(string value) {
             pb::ThrowHelper.ThrowIfNull(value, "value");
+            PrepareBuilder();
             result.hasAddress2 = true;
             result.address2_ = value;
             return this;
           }
           public Builder ClearAddress2() {
+            PrepareBuilder();
             result.hasAddress2 = false;
             result.address2_ = "";
             return this;
@@ -1017,11 +1129,13 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           public Builder SetCity(string value) {
             pb::ThrowHelper.ThrowIfNull(value, "value");
+            PrepareBuilder();
             result.hasCity = true;
             result.city_ = value;
             return this;
           }
           public Builder ClearCity() {
+            PrepareBuilder();
             result.hasCity = false;
             result.city_ = "";
             return this;
@@ -1036,11 +1150,13 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           public Builder SetState(string value) {
             pb::ThrowHelper.ThrowIfNull(value, "value");
+            PrepareBuilder();
             result.hasState = true;
             result.state_ = value;
             return this;
           }
           public Builder ClearState() {
+            PrepareBuilder();
             result.hasState = false;
             result.state_ = "";
             return this;
@@ -1056,11 +1172,13 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           [global::System.CLSCompliant(false)]
           public Builder SetZip(uint value) {
+            PrepareBuilder();
             result.hasZip = true;
             result.zip_ = value;
             return this;
           }
           public Builder ClearZip() {
+            PrepareBuilder();
             result.hasZip = false;
             result.zip_ = 0;
             return this;
@@ -1293,11 +1411,18 @@ namespace Google.ProtocolBuffers.TestProtos {
     public static TestInteropPersonLite ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
       return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
     }
+    private TestInteropPersonLite MakeReadOnly() {
+      codes_.MakeReadOnly();
+      phone_.MakeReadOnly();
+      addresses_.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(TestInteropPersonLite prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.SerializableAttribute()]
@@ -1308,21 +1433,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(TestInteropPersonLite cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
       
-      TestInteropPersonLite result = new TestInteropPersonLite();
+      private bool resultIsReadOnly;
+      private TestInteropPersonLite result;
+      
+      private TestInteropPersonLite PrepareBuilder() {
+        if (resultIsReadOnly) {
+          TestInteropPersonLite original = result;
+          result = new TestInteropPersonLite();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override TestInteropPersonLite MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new TestInteropPersonLite();
+        result = DefaultInstance;
+        resultIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override TestInteropPersonLite DefaultInstanceForType {
@@ -1330,15 +1482,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override TestInteropPersonLite BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (resultIsReadOnly) {
+          return result;
         }
-        result.codes_.MakeReadOnly();
-        result.phone_.MakeReadOnly();
-        result.addresses_.MakeReadOnly();
-        TestInteropPersonLite returnMe = result;
-        result = null;
-        return returnMe;
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
       }
       
       public override Builder MergeFrom(pb::IMessageLite other) {
@@ -1352,6 +1500,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(TestInteropPersonLite other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasName) {
           Name = other.Name;
         }
@@ -1362,13 +1511,13 @@ namespace Google.ProtocolBuffers.TestProtos {
           Email = other.Email;
         }
         if (other.codes_.Count != 0) {
-          base.AddRange(other.codes_, result.codes_);
+          result.codes_.Add(other.codes_);
         }
         if (other.phone_.Count != 0) {
-          base.AddRange(other.phone_, result.phone_);
+          result.phone_.Add(other.phone_);
         }
         if (other.addresses_.Count != 0) {
-          base.AddRange(other.addresses_, result.addresses_);
+          result.addresses_.Add(other.addresses_);
         }
           this.MergeExtensionFields(other);
         return this;
@@ -1379,6 +1528,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         uint tag;
         string field_name;
         while (input.ReadTag(out tag, out field_name)) {
@@ -1443,11 +1593,13 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       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;
@@ -1461,11 +1613,13 @@ namespace Google.ProtocolBuffers.TestProtos {
         set { SetId(value); }
       }
       public Builder SetId(int value) {
+        PrepareBuilder();
         result.hasId = true;
         result.id_ = value;
         return this;
       }
       public Builder ClearId() {
+        PrepareBuilder();
         result.hasId = false;
         result.id_ = 0;
         return this;
@@ -1480,18 +1634,20 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetEmail(string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasEmail = true;
         result.email_ = value;
         return this;
       }
       public Builder ClearEmail() {
+        PrepareBuilder();
         result.hasEmail = false;
         result.email_ = "";
         return this;
       }
       
       public pbc::IPopsicleList<int> CodesList {
-        get { return result.codes_; }
+        get { return PrepareBuilder().codes_; }
       }
       public int CodesCount {
         get { return result.CodesCount; }
@@ -1500,24 +1656,28 @@ namespace Google.ProtocolBuffers.TestProtos {
         return result.GetCodes(index);
       }
       public Builder SetCodes(int index, int value) {
+        PrepareBuilder();
         result.codes_[index] = value;
         return this;
       }
       public Builder AddCodes(int value) {
+        PrepareBuilder();
         result.codes_.Add(value);
         return this;
       }
       public Builder AddRangeCodes(scg::IEnumerable<int> values) {
-        base.AddRange(values, result.codes_);
+        PrepareBuilder();
+        result.codes_.Add(values);
         return this;
       }
       public Builder ClearCodes() {
+        PrepareBuilder();
         result.codes_.Clear();
         return this;
       }
       
       public pbc::IPopsicleList<global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber> PhoneList {
-        get { return result.phone_; }
+        get { return PrepareBuilder().phone_; }
       }
       public int PhoneCount {
         get { return result.PhoneCount; }
@@ -1527,35 +1687,41 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetPhone(int index, global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.phone_[index] = value;
         return this;
       }
       public Builder SetPhone(int index, global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.phone_[index] = builderForValue.Build();
         return this;
       }
       public Builder AddPhone(global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.phone_.Add(value);
         return this;
       }
       public Builder AddPhone(global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.phone_.Add(builderForValue.Build());
         return this;
       }
       public Builder AddRangePhone(scg::IEnumerable<global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber> values) {
-        base.AddRange(values, result.phone_);
+        PrepareBuilder();
+        result.phone_.Add(values);
         return this;
       }
       public Builder ClearPhone() {
+        PrepareBuilder();
         result.phone_.Clear();
         return this;
       }
       
       public pbc::IPopsicleList<global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses> AddressesList {
-        get { return result.addresses_; }
+        get { return PrepareBuilder().addresses_; }
       }
       public int AddressesCount {
         get { return result.AddressesCount; }
@@ -1565,29 +1731,35 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetAddresses(int index, global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.addresses_[index] = value;
         return this;
       }
       public Builder SetAddresses(int index, global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.addresses_[index] = builderForValue.Build();
         return this;
       }
       public Builder AddAddresses(global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.addresses_.Add(value);
         return this;
       }
       public Builder AddAddresses(global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.addresses_.Add(builderForValue.Build());
         return this;
       }
       public Builder AddRangeAddresses(scg::IEnumerable<global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses> values) {
-        base.AddRange(values, result.addresses_);
+        PrepareBuilder();
+        result.addresses_.Add(values);
         return this;
       }
       public Builder ClearAddresses() {
+        PrepareBuilder();
         result.addresses_.Clear();
         return this;
       }
@@ -1602,7 +1774,8 @@ namespace Google.ProtocolBuffers.TestProtos {
   [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
   [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
   public sealed partial class TestInteropEmployeeIdLite : pb::GeneratedMessageLite<TestInteropEmployeeIdLite, TestInteropEmployeeIdLite.Builder> {
-    private static readonly TestInteropEmployeeIdLite defaultInstance = new Builder().BuildPartial();
+    private TestInteropEmployeeIdLite() { }
+    private static readonly TestInteropEmployeeIdLite defaultInstance = new TestInteropEmployeeIdLite().MakeReadOnly();
     private static readonly string[] _testInteropEmployeeIdLiteFieldNames = new string[] { "number" };
     private static readonly uint[] _testInteropEmployeeIdLiteFieldTags = new uint[] { 10 };
     public static TestInteropEmployeeIdLite DefaultInstance {
@@ -1610,7 +1783,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     }
     
     public override TestInteropEmployeeIdLite DefaultInstanceForType {
-      get { return defaultInstance; }
+      get { return DefaultInstance; }
     }
     
     protected override TestInteropEmployeeIdLite ThisMessage {
@@ -1706,11 +1879,15 @@ namespace Google.ProtocolBuffers.TestProtos {
     public static TestInteropEmployeeIdLite ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
       return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
     }
+    private TestInteropEmployeeIdLite 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(TestInteropEmployeeIdLite prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.SerializableAttribute()]
@@ -1721,21 +1898,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(TestInteropEmployeeIdLite cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
       
-      TestInteropEmployeeIdLite result = new TestInteropEmployeeIdLite();
+      private bool resultIsReadOnly;
+      private TestInteropEmployeeIdLite result;
+      
+      private TestInteropEmployeeIdLite PrepareBuilder() {
+        if (resultIsReadOnly) {
+          TestInteropEmployeeIdLite original = result;
+          result = new TestInteropEmployeeIdLite();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override TestInteropEmployeeIdLite MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new TestInteropEmployeeIdLite();
+        result = DefaultInstance;
+        resultIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override TestInteropEmployeeIdLite DefaultInstanceForType {
@@ -1743,12 +1947,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override TestInteropEmployeeIdLite BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (resultIsReadOnly) {
+          return result;
         }
-        TestInteropEmployeeIdLite returnMe = result;
-        result = null;
-        return returnMe;
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
       }
       
       public override Builder MergeFrom(pb::IMessageLite other) {
@@ -1762,6 +1965,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(TestInteropEmployeeIdLite other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.TestInteropEmployeeIdLite.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasNumber) {
           Number = other.Number;
         }
@@ -1773,6 +1977,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         uint tag;
         string field_name;
         while (input.ReadTag(out tag, out field_name)) {
@@ -1816,11 +2021,13 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetNumber(string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasNumber = true;
         result.number_ = value;
         return this;
       }
       public Builder ClearNumber() {
+        PrepareBuilder();
         result.hasNumber = false;
         result.number_ = "";
         return this;

+ 49 - 14
src/ProtocolBuffersLite.Test/TestProtos/UnitTestImportLiteProtoFile.cs

@@ -1,5 +1,5 @@
 // Generated by ProtoGen, Version=2.3.0.277, Culture=neutral, PublicKeyToken=17b3b1f090c3ea48.  DO NOT EDIT!
-#pragma warning disable 1591
+#pragma warning disable 1591, 0612
 #region Designer generated code
 
 using pb = global::Google.ProtocolBuffers;
@@ -43,7 +43,8 @@ namespace Google.ProtocolBuffers.TestProtos {
   [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
   [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
   public sealed partial class ImportMessageLite : pb::GeneratedMessageLite<ImportMessageLite, ImportMessageLite.Builder> {
-    private static readonly ImportMessageLite defaultInstance = new Builder().BuildPartial();
+    private ImportMessageLite() { }
+    private static readonly ImportMessageLite defaultInstance = new ImportMessageLite().MakeReadOnly();
     private static readonly string[] _importMessageLiteFieldNames = new string[] { "d" };
     private static readonly uint[] _importMessageLiteFieldTags = new uint[] { 8 };
     public static ImportMessageLite DefaultInstance {
@@ -51,7 +52,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     }
     
     public override ImportMessageLite DefaultInstanceForType {
-      get { return defaultInstance; }
+      get { return DefaultInstance; }
     }
     
     protected override ImportMessageLite ThisMessage {
@@ -146,11 +147,15 @@ namespace Google.ProtocolBuffers.TestProtos {
     public static ImportMessageLite ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
       return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
     }
+    private ImportMessageLite 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(ImportMessageLite prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -160,21 +165,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(ImportMessageLite cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
+      
+      private bool resultIsReadOnly;
+      private ImportMessageLite result;
+      
+      private ImportMessageLite PrepareBuilder() {
+        if (resultIsReadOnly) {
+          ImportMessageLite original = result;
+          result = new ImportMessageLite();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
       
-      ImportMessageLite result = new ImportMessageLite();
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override ImportMessageLite MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new ImportMessageLite();
+        result = DefaultInstance;
+        resultIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override ImportMessageLite DefaultInstanceForType {
@@ -182,12 +214,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override ImportMessageLite BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (resultIsReadOnly) {
+          return result;
         }
-        ImportMessageLite returnMe = result;
-        result = null;
-        return returnMe;
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
       }
       
       public override Builder MergeFrom(pb::IMessageLite other) {
@@ -201,6 +232,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(ImportMessageLite other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.ImportMessageLite.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasD) {
           D = other.D;
         }
@@ -212,6 +244,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         uint tag;
         string field_name;
         while (input.ReadTag(out tag, out field_name)) {
@@ -254,11 +287,13 @@ namespace Google.ProtocolBuffers.TestProtos {
         set { SetD(value); }
       }
       public Builder SetD(int value) {
+        PrepareBuilder();
         result.hasD = true;
         result.d_ = value;
         return this;
       }
       public Builder ClearD() {
+        PrepareBuilder();
         result.hasD = false;
         result.d_ = 0;
         return this;

+ 49 - 14
src/ProtocolBuffersLite.Test/TestProtos/UnitTestImportProtoFile.cs

@@ -1,5 +1,5 @@
 // Generated by ProtoGen, Version=2.3.0.277, Culture=neutral, PublicKeyToken=17b3b1f090c3ea48.  DO NOT EDIT!
-#pragma warning disable 1591
+#pragma warning disable 1591, 0612
 #region Designer generated code
 
 using pb = global::Google.ProtocolBuffers;
@@ -71,7 +71,8 @@ namespace Google.ProtocolBuffers.TestProtos {
   [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
   [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
   public sealed partial class ImportMessage : pb::GeneratedMessage<ImportMessage, ImportMessage.Builder> {
-    private static readonly ImportMessage defaultInstance = new Builder().BuildPartial();
+    private ImportMessage() { }
+    private static readonly ImportMessage defaultInstance = new ImportMessage().MakeReadOnly();
     private static readonly string[] _importMessageFieldNames = new string[] { "d" };
     private static readonly uint[] _importMessageFieldTags = new uint[] { 8 };
     public static ImportMessage DefaultInstance {
@@ -79,7 +80,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     }
     
     public override ImportMessage DefaultInstanceForType {
-      get { return defaultInstance; }
+      get { return DefaultInstance; }
     }
     
     protected override ImportMessage ThisMessage {
@@ -165,11 +166,15 @@ namespace Google.ProtocolBuffers.TestProtos {
     public static ImportMessage ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
       return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
     }
+    private ImportMessage 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(ImportMessage prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -179,21 +184,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(ImportMessage cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
+      
+      private bool resultIsReadOnly;
+      private ImportMessage result;
+      
+      private ImportMessage PrepareBuilder() {
+        if (resultIsReadOnly) {
+          ImportMessage original = result;
+          result = new ImportMessage();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
       
-      ImportMessage result = new ImportMessage();
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override ImportMessage MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new ImportMessage();
+        result = DefaultInstance;
+        resultIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -205,12 +237,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override ImportMessage BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (resultIsReadOnly) {
+          return result;
         }
-        ImportMessage returnMe = result;
-        result = null;
-        return returnMe;
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -224,6 +255,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(ImportMessage other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.ImportMessage.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasD) {
           D = other.D;
         }
@@ -236,6 +268,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -291,11 +324,13 @@ namespace Google.ProtocolBuffers.TestProtos {
         set { SetD(value); }
       }
       public Builder SetD(int value) {
+        PrepareBuilder();
         result.hasD = true;
         result.d_ = value;
         return this;
       }
       public Builder ClearD() {
+        PrepareBuilder();
         result.hasD = false;
         result.d_ = 0;
         return this;

+ 54 - 17
src/ProtocolBuffersLite.Test/TestProtos/UnitTestLiteImportNonLiteProtoFile.cs

@@ -1,5 +1,5 @@
 // Generated by ProtoGen, Version=2.3.0.277, Culture=neutral, PublicKeyToken=17b3b1f090c3ea48.  DO NOT EDIT!
-#pragma warning disable 1591
+#pragma warning disable 1591, 0612
 #region Designer generated code
 
 using pb = global::Google.ProtocolBuffers;
@@ -32,7 +32,8 @@ namespace Google.ProtocolBuffers.TestProtos {
   [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
   [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
   public sealed partial class TestLiteImportsNonlite : pb::GeneratedMessageLite<TestLiteImportsNonlite, TestLiteImportsNonlite.Builder> {
-    private static readonly TestLiteImportsNonlite defaultInstance = new Builder().BuildPartial();
+    private TestLiteImportsNonlite() { }
+    private static readonly TestLiteImportsNonlite defaultInstance = new TestLiteImportsNonlite().MakeReadOnly();
     private static readonly string[] _testLiteImportsNonliteFieldNames = new string[] { "message" };
     private static readonly uint[] _testLiteImportsNonliteFieldTags = new uint[] { 10 };
     public static TestLiteImportsNonlite DefaultInstance {
@@ -40,7 +41,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     }
     
     public override TestLiteImportsNonlite DefaultInstanceForType {
-      get { return defaultInstance; }
+      get { return DefaultInstance; }
     }
     
     protected override TestLiteImportsNonlite ThisMessage {
@@ -49,12 +50,12 @@ namespace Google.ProtocolBuffers.TestProtos {
     
     public const int MessageFieldNumber = 1;
     private bool hasMessage;
-    private global::Google.ProtocolBuffers.TestProtos.TestAllTypes message_ = global::Google.ProtocolBuffers.TestProtos.TestAllTypes.DefaultInstance;
+    private global::Google.ProtocolBuffers.TestProtos.TestAllTypes message_;
     public bool HasMessage {
       get { return hasMessage; }
     }
     public global::Google.ProtocolBuffers.TestProtos.TestAllTypes Message {
-      get { return message_; }
+      get { return message_ ?? global::Google.ProtocolBuffers.TestProtos.TestAllTypes.DefaultInstance; }
     }
     
     public override bool IsInitialized {
@@ -135,11 +136,15 @@ namespace Google.ProtocolBuffers.TestProtos {
     public static TestLiteImportsNonlite ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
       return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
     }
+    private TestLiteImportsNonlite 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(TestLiteImportsNonlite prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -149,21 +154,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(TestLiteImportsNonlite cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
+      
+      private bool resultIsReadOnly;
+      private TestLiteImportsNonlite result;
+      
+      private TestLiteImportsNonlite PrepareBuilder() {
+        if (resultIsReadOnly) {
+          TestLiteImportsNonlite original = result;
+          result = new TestLiteImportsNonlite();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
       
-      TestLiteImportsNonlite result = new TestLiteImportsNonlite();
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override TestLiteImportsNonlite MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new TestLiteImportsNonlite();
+        result = DefaultInstance;
+        resultIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override TestLiteImportsNonlite DefaultInstanceForType {
@@ -171,12 +203,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override TestLiteImportsNonlite BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (resultIsReadOnly) {
+          return result;
         }
-        TestLiteImportsNonlite returnMe = result;
-        result = null;
-        return returnMe;
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
       }
       
       public override Builder MergeFrom(pb::IMessageLite other) {
@@ -190,6 +221,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(TestLiteImportsNonlite other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.TestLiteImportsNonlite.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasMessage) {
           MergeMessage(other.Message);
         }
@@ -201,6 +233,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         uint tag;
         string field_name;
         while (input.ReadTag(out tag, out field_name)) {
@@ -249,18 +282,21 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetMessage(global::Google.ProtocolBuffers.TestProtos.TestAllTypes value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasMessage = true;
         result.message_ = value;
         return this;
       }
       public Builder SetMessage(global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.hasMessage = true;
         result.message_ = builderForValue.Build();
         return this;
       }
       public Builder MergeMessage(global::Google.ProtocolBuffers.TestProtos.TestAllTypes value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         if (result.hasMessage &&
             result.message_ != global::Google.ProtocolBuffers.TestProtos.TestAllTypes.DefaultInstance) {
             result.message_ = global::Google.ProtocolBuffers.TestProtos.TestAllTypes.CreateBuilder(result.message_).MergeFrom(value).BuildPartial();
@@ -271,8 +307,9 @@ namespace Google.ProtocolBuffers.TestProtos {
         return this;
       }
       public Builder ClearMessage() {
+        PrepareBuilder();
         result.hasMessage = false;
-        result.message_ = global::Google.ProtocolBuffers.TestProtos.TestAllTypes.DefaultInstance;
+        result.message_ = null;
         return this;
       }
     }

Plik diff jest za duży
+ 286 - 111
src/ProtocolBuffersLite.Test/TestProtos/UnitTestLiteProtoFile.cs


Plik diff jest za duży
+ 286 - 111
src/ProtocolBuffersLite.Test/TestProtos/UnitTestProtoFile.cs


+ 0 - 16
todo.txt

@@ -1,16 +0,0 @@
-Current task list (not in order)
-
-- Remove multifile support
-- Docs
-- Clean up protogen code
-- Avoid using reflection for messages which don't need it (is this
-  possible?)
-- Bring service generation into line with Java
-- Build protoc as a dll and use directly from protogen
-- Check copyright is everywhere
-- Work out how to unit test Silverlight code
-- Reformat code
-- Change generated format
-- Add regions to copyright
-- Build and publish binaries
-- Work out why the Compact Framework 3.5 build fails under VS2010

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików