Selaa lähdekoodia

Merge pull request #625 from jskeet/reflection-refactor

Reflection refactor
Jan Tattermusch 10 vuotta sitten
vanhempi
commit
7b5c396799
48 muutettua tiedostoa jossa 772 lisäystä ja 1274 poistoa
  1. 1 1
      Makefile.am
  2. 12 29
      csharp/src/AddressBook/Addressbook.cs
  3. 24 23
      csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs
  4. 1 0
      csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs
  5. 25 62
      csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs
  6. 7 14
      csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs
  7. 7 13
      csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs
  8. 29 64
      csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs
  9. 119 292
      csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs
  10. 16 47
      csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs
  11. 3 3
      csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs
  12. 3 0
      csharp/src/Google.Protobuf/Collections/MapField.cs
  13. 1 1
      csharp/src/Google.Protobuf/Google.Protobuf.csproj
  14. 8 10
      csharp/src/Google.Protobuf/IMessage.cs
  15. 13 13
      csharp/src/Google.Protobuf/JsonFormatter.cs
  16. 67 181
      csharp/src/Google.Protobuf/Reflection/DescriptorProtoFile.cs
  17. 2 3
      csharp/src/Google.Protobuf/Reflection/DescriptorUtil.cs
  18. 9 1
      csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs
  19. 1 6
      csharp/src/Google.Protobuf/Reflection/FieldAccessorBase.cs
  20. 0 97
      csharp/src/Google.Protobuf/Reflection/FieldAccessorTable.cs
  21. 29 1
      csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs
  22. 18 8
      csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs
  23. 66 0
      csharp/src/Google.Protobuf/Reflection/GeneratedCodeInfo.cs
  24. 2 1
      csharp/src/Google.Protobuf/Reflection/MapFieldAccessor.cs
  25. 50 18
      csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs
  26. 4 6
      csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs
  27. 26 1
      csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs
  28. 2 1
      csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs
  29. 2 1
      csharp/src/Google.Protobuf/Reflection/RepeatedFieldAccessor.cs
  30. 1 4
      csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs
  31. 7 13
      csharp/src/Google.Protobuf/WellKnownTypes/Any.cs
  32. 10 23
      csharp/src/Google.Protobuf/WellKnownTypes/Api.cs
  33. 7 13
      csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs
  34. 7 13
      csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs
  35. 7 13
      csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs
  36. 7 13
      csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs
  37. 13 29
      csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs
  38. 7 13
      csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs
  39. 19 47
      csharp/src/Google.Protobuf/WellKnownTypes/Type.cs
  40. 31 77
      csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs
  41. 0 5
      src/google/protobuf/compiler/csharp/csharp_field_base.cc
  42. 0 1
      src/google/protobuf/compiler/csharp/csharp_field_base.h
  43. 2 4
      src/google/protobuf/compiler/csharp/csharp_helpers.h
  44. 3 92
      src/google/protobuf/compiler/csharp/csharp_message.cc
  45. 0 2
      src/google/protobuf/compiler/csharp/csharp_message.h
  46. 1 1
      src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
  47. 102 14
      src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc
  48. 1 0
      src/google/protobuf/compiler/csharp/csharp_umbrella_class.h

+ 1 - 1
Makefile.am

@@ -117,10 +117,10 @@ csharp_EXTRA_DIST=                                                           \
   csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs                    \
   csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs               \
   csharp/src/Google.Protobuf/Reflection/FieldAccessorBase.cs                 \
-  csharp/src/Google.Protobuf/Reflection/FieldAccessorTable.cs                \
   csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs                   \
   csharp/src/Google.Protobuf/Reflection/FieldType.cs                         \
   csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs                    \
+  csharp/src/Google.Protobuf/Reflection/GeneratedCodeInfo.cs                 \
   csharp/src/Google.Protobuf/Reflection/IDescriptor.cs                       \
   csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs                    \
   csharp/src/Google.Protobuf/Reflection/MapFieldAccessor.cs                  \

+ 12 - 29
csharp/src/AddressBook/Addressbook.cs

@@ -12,11 +12,6 @@ namespace Google.Protobuf.Examples.AddressBook {
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
   public static partial class Addressbook {
 
-    #region Static variables
-    internal static pbr::FieldAccessorTable internal__static_tutorial_Person__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_tutorial_Person_PhoneNumber__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_tutorial_AddressBook__FieldAccessorTable;
-    #endregion
     #region Descriptor
     public static pbr::FileDescriptor Descriptor {
       get { return descriptor; }
@@ -34,19 +29,13 @@ namespace Google.Protobuf.Examples.AddressBook {
             "EggKBEhPTUUQARIICgRXT1JLEAIiLwoLQWRkcmVzc0Jvb2sSIAoGcGVvcGxl", 
             "GAEgAygLMhAudHV0b3JpYWwuUGVyc29uQlAKFGNvbS5leGFtcGxlLnR1dG9y", 
             "aWFsQhFBZGRyZXNzQm9va1Byb3Rvc6oCJEdvb2dsZS5Qcm90b2J1Zi5FeGFt", 
-          "cGxlcy5BZGRyZXNzQm9va2IGcHJvdG8z"));
+            "cGxlcy5BZGRyZXNzQm9va2IGcHJvdG8z"));
       descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
-          new pbr::FileDescriptor[] {
-          });
-      internal__static_tutorial_Person__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.Examples.AddressBook.Person), descriptor.MessageTypes[0],
-              new string[] { "Name", "Id", "Email", "Phones", }, new string[] { });
-      internal__static_tutorial_Person_PhoneNumber__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber), descriptor.MessageTypes[0].NestedTypes[0],
-              new string[] { "Number", "Type", }, new string[] { });
-      internal__static_tutorial_AddressBook__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.Examples.AddressBook.AddressBook), descriptor.MessageTypes[1],
-              new string[] { "People", }, new string[] { });
+          new pbr::FileDescriptor[] { },
+          new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Examples.AddressBook.Person), new[]{ "Name", "Id", "Email", "Phones" }, null, new[]{ typeof(global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType) }, new pbr::GeneratedCodeInfo[] { new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber), new[]{ "Number", "Type" }, null, null, null)}),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Examples.AddressBook.AddressBook), new[]{ "People" }, null, null, null)
+          }));
     }
     #endregion
 
@@ -57,14 +46,12 @@ namespace Google.Protobuf.Examples.AddressBook {
     private static readonly pb::MessageParser<Person> _parser = new pb::MessageParser<Person>(() => new Person());
     public static pb::MessageParser<Person> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "email", "id", "name", "phones" };
-    private static readonly uint[] _fieldTags = new uint[] { 26, 16, 10, 34 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Examples.AddressBook.Addressbook.Descriptor.MessageTypes[0]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.Examples.AddressBook.Addressbook.internal__static_tutorial_Person__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -256,14 +243,12 @@ namespace Google.Protobuf.Examples.AddressBook {
         private static readonly pb::MessageParser<PhoneNumber> _parser = new pb::MessageParser<PhoneNumber>(() => new PhoneNumber());
         public static pb::MessageParser<PhoneNumber> Parser { get { return _parser; } }
 
-        private static readonly string[] _fieldNames = new string[] { "number", "type" };
-        private static readonly uint[] _fieldTags = new uint[] { 10, 16 };
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.Examples.AddressBook.Person.Descriptor.NestedTypes[0]; }
         }
 
-        pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-          get { return global::Google.Protobuf.Examples.AddressBook.Addressbook.internal__static_tutorial_Person_PhoneNumber__FieldAccessorTable; }
+        pbr::MessageDescriptor pb::IMessage.Descriptor {
+          get { return Descriptor; }
         }
 
         private bool _frozen = false;
@@ -407,14 +392,12 @@ namespace Google.Protobuf.Examples.AddressBook {
     private static readonly pb::MessageParser<AddressBook> _parser = new pb::MessageParser<AddressBook>(() => new AddressBook());
     public static pb::MessageParser<AddressBook> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "people" };
-    private static readonly uint[] _fieldTags = new uint[] { 10 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Examples.AddressBook.Addressbook.Descriptor.MessageTypes[1]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.Examples.AddressBook.Addressbook.internal__static_tutorial_AddressBook__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;

+ 24 - 23
csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs

@@ -604,7 +604,7 @@ namespace Google.Protobuf
         public void Reflection_GetValue()
         {
             var message = SampleMessages.CreateFullTestAllTypes();
-            var fields = ((IReflectedMessage) message).Fields;
+            var fields = TestAllTypes.Descriptor.FieldAccessorsByFieldNumber;
             Assert.AreEqual(message.SingleBool, fields[TestAllTypes.SingleBoolFieldNumber].GetValue(message));
             Assert.AreEqual(message.SingleBytes, fields[TestAllTypes.SingleBytesFieldNumber].GetValue(message));
             Assert.AreEqual(message.SingleDouble, fields[TestAllTypes.SingleDoubleFieldNumber].GetValue(message));
@@ -639,7 +639,7 @@ namespace Google.Protobuf
 
             // Just a single map field, for the same reason
             var mapMessage = new TestMap { MapStringString = { { "key1", "value1" }, { "key2", "value2" } } };
-            fields = ((IReflectedMessage) mapMessage).Fields;
+            fields = TestMap.Descriptor.FieldAccessorsByFieldNumber;
             var dictionary = (IDictionary) fields[TestMap.MapStringStringFieldNumber].GetValue(mapMessage);
             Assert.AreEqual(mapMessage.MapStringString, dictionary);
             Assert.AreEqual("value1", dictionary["key1"]);
@@ -648,8 +648,8 @@ namespace Google.Protobuf
         [Test]
         public void Reflection_Clear()
         {
-            IReflectedMessage message = SampleMessages.CreateFullTestAllTypes();
-            var fields = message.Fields;
+            var message = SampleMessages.CreateFullTestAllTypes();
+            var fields = TestAllTypes.Descriptor.FieldAccessorsByFieldNumber;
             fields[TestAllTypes.SingleBoolFieldNumber].Clear(message);
             fields[TestAllTypes.SingleInt32FieldNumber].Clear(message);
             fields[TestAllTypes.SingleStringFieldNumber].Clear(message);
@@ -673,7 +673,7 @@ namespace Google.Protobuf
 
             // Separately, maps.
             var mapMessage = new TestMap { MapStringString = { { "key1", "value1" }, { "key2", "value2" } } };
-            fields = ((IReflectedMessage) mapMessage).Fields;
+            fields = TestMap.Descriptor.FieldAccessorsByFieldNumber;
             fields[TestMap.MapStringStringFieldNumber].Clear(mapMessage);
             Assert.AreEqual(0, mapMessage.MapStringString.Count);
         }
@@ -682,8 +682,8 @@ namespace Google.Protobuf
         public void Reflection_SetValue_SingleFields()
         {
             // Just a sample (primitives, messages, enums, strings, byte strings)
-            IReflectedMessage message = SampleMessages.CreateFullTestAllTypes();
-            var fields = message.Fields;
+            var message = SampleMessages.CreateFullTestAllTypes();
+            var fields = TestAllTypes.Descriptor.FieldAccessorsByFieldNumber;
             fields[TestAllTypes.SingleBoolFieldNumber].SetValue(message, false);
             fields[TestAllTypes.SingleInt32FieldNumber].SetValue(message, 500);
             fields[TestAllTypes.SingleStringFieldNumber].SetValue(message, "It's a string");
@@ -709,51 +709,52 @@ namespace Google.Protobuf
         [Test]
         public void Reflection_SetValue_SingleFields_WrongType()
         {
-            IReflectedMessage message = SampleMessages.CreateFullTestAllTypes();
-            var fields = message.Fields;
+            IMessage message = SampleMessages.CreateFullTestAllTypes();
+            var fields = message.Descriptor.FieldAccessorsByFieldNumber;
             Assert.Throws<InvalidCastException>(() => fields[TestAllTypes.SingleBoolFieldNumber].SetValue(message, "This isn't a bool"));
         }
 
         [Test]
         public void Reflection_SetValue_MapFields()
         {
-            IReflectedMessage message = new TestMap();
-            var fields = message.Fields;
+            IMessage message = new TestMap();
+            var fields = message.Descriptor.FieldAccessorsByFieldNumber;
             Assert.Throws<InvalidOperationException>(() => fields[TestMap.MapStringStringFieldNumber].SetValue(message, new Dictionary<string, string>()));
         }
 
         [Test]
         public void Reflection_SetValue_RepeatedFields()
         {
-            IReflectedMessage message = SampleMessages.CreateFullTestAllTypes();
-            var fields = message.Fields;
+            IMessage message = SampleMessages.CreateFullTestAllTypes();
+            var fields = message.Descriptor.FieldAccessorsByFieldNumber;
             Assert.Throws<InvalidOperationException>(() => fields[TestAllTypes.RepeatedDoubleFieldNumber].SetValue(message, new double[10]));
         }
 
         [Test]
         public void Reflection_GetValue_IncorrectType()
         {
-            IReflectedMessage message = SampleMessages.CreateFullTestAllTypes();
-            Assert.Throws<InvalidCastException>(() => message.Fields[TestAllTypes.SingleBoolFieldNumber].GetValue(new TestMap()));
+            IMessage message = SampleMessages.CreateFullTestAllTypes();
+            var fields = message.Descriptor.FieldAccessorsByFieldNumber;
+            Assert.Throws<InvalidCastException>(() => fields[TestAllTypes.SingleBoolFieldNumber].GetValue(new TestMap()));
         }
 
         [Test]
         public void Reflection_Oneof()
         {
             var message = new TestAllTypes();
-            var fields = ((IReflectedMessage) message).Fields;
-            Assert.AreEqual(1, fields.Oneofs.Count);
-            var oneof = fields.Oneofs[0];
-            Assert.AreEqual("oneof_field", oneof.Descriptor.Name);
-            Assert.IsNull(oneof.GetCaseFieldDescriptor(message));
+            var descriptor = TestAllTypes.Descriptor;
+            Assert.AreEqual(1, descriptor.Oneofs.Count);
+            var oneof = descriptor.Oneofs[0];
+            Assert.AreEqual("oneof_field", oneof.Name);
+            Assert.IsNull(oneof.Accessor.GetCaseFieldDescriptor(message));
 
             message.OneofString = "foo";
-            Assert.AreSame(fields[TestAllTypes.OneofStringFieldNumber].Descriptor, oneof.GetCaseFieldDescriptor(message));
+            Assert.AreSame(descriptor.FieldAccessorsByFieldNumber[TestAllTypes.OneofStringFieldNumber].Descriptor, oneof.Accessor.GetCaseFieldDescriptor(message));
 
             message.OneofUint32 = 10;
-            Assert.AreSame(fields[TestAllTypes.OneofUint32FieldNumber].Descriptor, oneof.GetCaseFieldDescriptor(message));
+            Assert.AreSame(descriptor.FieldAccessorsByFieldNumber[TestAllTypes.OneofUint32FieldNumber].Descriptor, oneof.Accessor.GetCaseFieldDescriptor(message));
 
-            oneof.Clear(message);
+            oneof.Accessor.Clear(message);
             Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
         }
     }

+ 1 - 0
csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs

@@ -62,6 +62,7 @@ namespace Google.Protobuf.Reflection
             Assert.AreEqual(UnittestImportProto3.Descriptor, file.Dependencies[0]);
 
             MessageDescriptor messageType = TestAllTypes.Descriptor;
+            Assert.AreSame(typeof(TestAllTypes), messageType.GeneratedType);
             Assert.AreEqual(messageType, file.MessageTypes[0]);
             Assert.AreEqual(messageType, file.FindTypeByName<MessageDescriptor>("TestAllTypes"));
             Assert.Null(file.FindTypeByName<MessageDescriptor>("NoSuchType"));

+ 25 - 62
csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs

@@ -12,15 +12,6 @@ namespace Google.Protobuf.TestProtos {
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
   public static partial class MapUnittestProto3 {
 
-    #region Static variables
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_TestMap__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_TestMapSubmessage__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_TestMessageMap__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_TestSameTypeMap__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_TestArenaMap__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_MessageContainingEnumCalledType__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_MessageContainingMapCalledEntry__FieldAccessorTable;
-    #endregion
     #region Descriptor
     public static pbr::FileDescriptor Descriptor {
       get { return descriptor; }
@@ -153,32 +144,18 @@ namespace Google.Protobuf.TestProtos {
             "dHJ5LkVudHJ5RW50cnkaLAoKRW50cnlFbnRyeRILCgNrZXkYASABKAUSDQoF", 
             "dmFsdWUYAiABKAU6AjgBKj8KB01hcEVudW0SEAoMTUFQX0VOVU1fRk9PEAAS", 
             "EAoMTUFQX0VOVU1fQkFSEAESEAoMTUFQX0VOVU1fQkFaEAJCIPgBAaoCGkdv", 
-          "b2dsZS5Qcm90b2J1Zi5UZXN0UHJvdG9zYgZwcm90bzM="));
+            "b2dsZS5Qcm90b2J1Zi5UZXN0UHJvdG9zYgZwcm90bzM="));
       descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
-          new pbr::FileDescriptor[] {
-          global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor, 
-          });
-      internal__static_protobuf_unittest_TestMap__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestMap), descriptor.MessageTypes[0],
-              new string[] { "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapStringString", "MapInt32Bytes", "MapInt32Enum", "MapInt32ForeignMessage", }, new string[] { });
-      internal__static_protobuf_unittest_TestMapSubmessage__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestMapSubmessage), descriptor.MessageTypes[1],
-              new string[] { "TestMap", }, new string[] { });
-      internal__static_protobuf_unittest_TestMessageMap__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestMessageMap), descriptor.MessageTypes[2],
-              new string[] { "MapInt32Message", }, new string[] { });
-      internal__static_protobuf_unittest_TestSameTypeMap__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestSameTypeMap), descriptor.MessageTypes[3],
-              new string[] { "Map1", "Map2", }, new string[] { });
-      internal__static_protobuf_unittest_TestArenaMap__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestArenaMap), descriptor.MessageTypes[4],
-              new string[] { "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapInt32Enum", "MapInt32ForeignMessage", }, new string[] { });
-      internal__static_protobuf_unittest_MessageContainingEnumCalledType__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType), descriptor.MessageTypes[5],
-              new string[] { "Type", }, new string[] { });
-      internal__static_protobuf_unittest_MessageContainingMapCalledEntry__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.MessageContainingMapCalledEntry), descriptor.MessageTypes[6],
-              new string[] { "Entry", }, new string[] { });
+          new pbr::FileDescriptor[] { global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor, },
+          new pbr::GeneratedCodeInfo(new[] {typeof(global::Google.Protobuf.TestProtos.MapEnum), }, new pbr::GeneratedCodeInfo[] {
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestMap), new[]{ "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapStringString", "MapInt32Bytes", "MapInt32Enum", "MapInt32ForeignMessage" }, null, null, new pbr::GeneratedCodeInfo[] { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, }),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestMapSubmessage), new[]{ "TestMap" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestMessageMap), new[]{ "MapInt32Message" }, null, null, new pbr::GeneratedCodeInfo[] { null, }),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestSameTypeMap), new[]{ "Map1", "Map2" }, null, null, new pbr::GeneratedCodeInfo[] { null, null, }),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestArenaMap), new[]{ "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapInt32Enum", "MapInt32ForeignMessage" }, null, null, new pbr::GeneratedCodeInfo[] { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, }),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType), new[]{ "Type" }, null, new[]{ typeof(global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType.Types.Type) }, new pbr::GeneratedCodeInfo[] { null, }),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.MessageContainingMapCalledEntry), new[]{ "Entry" }, null, null, new pbr::GeneratedCodeInfo[] { null, })
+          }));
     }
     #endregion
 
@@ -198,14 +175,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<TestMap> _parser = new pb::MessageParser<TestMap>(() => new TestMap());
     public static pb::MessageParser<TestMap> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "map_bool_bool", "map_fixed32_fixed32", "map_fixed64_fixed64", "map_int32_bytes", "map_int32_double", "map_int32_enum", "map_int32_float", "map_int32_foreign_message", "map_int32_int32", "map_int64_int64", "map_sfixed32_sfixed32", "map_sfixed64_sfixed64", "map_sint32_sint32", "map_sint64_sint64", "map_string_string", "map_uint32_uint32", "map_uint64_uint64" };
-    private static readonly uint[] _fieldTags = new uint[] { 106, 58, 66, 122, 98, 130, 90, 138, 10, 18, 74, 82, 42, 50, 114, 26, 34 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.Descriptor.MessageTypes[0]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -613,14 +588,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<TestMapSubmessage> _parser = new pb::MessageParser<TestMapSubmessage>(() => new TestMapSubmessage());
     public static pb::MessageParser<TestMapSubmessage> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "test_map" };
-    private static readonly uint[] _fieldTags = new uint[] { 10 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.Descriptor.MessageTypes[1]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMapSubmessage__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -739,14 +712,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<TestMessageMap> _parser = new pb::MessageParser<TestMessageMap>(() => new TestMessageMap());
     public static pb::MessageParser<TestMessageMap> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "map_int32_message" };
-    private static readonly uint[] _fieldTags = new uint[] { 10 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.Descriptor.MessageTypes[2]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMessageMap__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -850,14 +821,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<TestSameTypeMap> _parser = new pb::MessageParser<TestSameTypeMap>(() => new TestSameTypeMap());
     public static pb::MessageParser<TestSameTypeMap> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "map1", "map2" };
-    private static readonly uint[] _fieldTags = new uint[] { 10, 18 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.Descriptor.MessageTypes[3]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestSameTypeMap__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -980,14 +949,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<TestArenaMap> _parser = new pb::MessageParser<TestArenaMap>(() => new TestArenaMap());
     public static pb::MessageParser<TestArenaMap> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "map_bool_bool", "map_fixed32_fixed32", "map_fixed64_fixed64", "map_int32_double", "map_int32_enum", "map_int32_float", "map_int32_foreign_message", "map_int32_int32", "map_int64_int64", "map_sfixed32_sfixed32", "map_sfixed64_sfixed64", "map_sint32_sint32", "map_sint64_sint64", "map_uint32_uint32", "map_uint64_uint64" };
-    private static readonly uint[] _fieldTags = new uint[] { 106, 58, 66, 98, 114, 90, 122, 10, 18, 74, 82, 42, 50, 26, 34 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.Descriptor.MessageTypes[4]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -1357,14 +1324,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<MessageContainingEnumCalledType> _parser = new pb::MessageParser<MessageContainingEnumCalledType>(() => new MessageContainingEnumCalledType());
     public static pb::MessageParser<MessageContainingEnumCalledType> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "type" };
-    private static readonly uint[] _fieldTags = new uint[] { 10 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.Descriptor.MessageTypes[5]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_MessageContainingEnumCalledType__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -1478,14 +1443,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<MessageContainingMapCalledEntry> _parser = new pb::MessageParser<MessageContainingMapCalledEntry>(() => new MessageContainingMapCalledEntry());
     public static pb::MessageParser<MessageContainingMapCalledEntry> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "entry" };
-    private static readonly uint[] _fieldTags = new uint[] { 10 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.Descriptor.MessageTypes[6]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_MessageContainingMapCalledEntry__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;

+ 7 - 14
csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs

@@ -12,9 +12,6 @@ namespace Google.Protobuf.TestProtos {
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
   public static partial class UnittestImportProto3 {
 
-    #region Static variables
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_import_ImportMessage__FieldAccessorTable;
-    #endregion
     #region Descriptor
     public static pbr::FileDescriptor Descriptor {
       get { return descriptor; }
@@ -31,14 +28,12 @@ namespace Google.Protobuf.TestProtos {
             "VU1fVU5TUEVDSUZJRUQQABIOCgpJTVBPUlRfRk9PEAcSDgoKSU1QT1JUX0JB", 
             "UhAIEg4KCklNUE9SVF9CQVoQCUI8Chhjb20uZ29vZ2xlLnByb3RvYnVmLnRl", 
             "c3RIAfgBAaoCGkdvb2dsZS5Qcm90b2J1Zi5UZXN0UHJvdG9zUABiBnByb3Rv", 
-          "Mw=="));
+            "Mw=="));
       descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
-          new pbr::FileDescriptor[] {
-          global::Google.Protobuf.TestProtos.UnittestImportPublicProto3.Descriptor, 
-          });
-      internal__static_protobuf_unittest_import_ImportMessage__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.ImportMessage), descriptor.MessageTypes[0],
-              new string[] { "D", }, new string[] { });
+          new pbr::FileDescriptor[] { global::Google.Protobuf.TestProtos.UnittestImportPublicProto3.Descriptor, },
+          new pbr::GeneratedCodeInfo(new[] {typeof(global::Google.Protobuf.TestProtos.ImportEnum), }, new pbr::GeneratedCodeInfo[] {
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.ImportMessage), new[]{ "D" }, null, null, null)
+          }));
     }
     #endregion
 
@@ -59,14 +54,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<ImportMessage> _parser = new pb::MessageParser<ImportMessage>(() => new ImportMessage());
     public static pb::MessageParser<ImportMessage> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "d" };
-    private static readonly uint[] _fieldTags = new uint[] { 8 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestImportProto3.Descriptor.MessageTypes[0]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestImportProto3.internal__static_protobuf_unittest_import_ImportMessage__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;

+ 7 - 13
csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs

@@ -12,9 +12,6 @@ namespace Google.Protobuf.TestProtos {
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
   public static partial class UnittestImportPublicProto3 {
 
-    #region Static variables
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_import_PublicImportMessage__FieldAccessorTable;
-    #endregion
     #region Descriptor
     public static pbr::FileDescriptor Descriptor {
       get { return descriptor; }
@@ -27,13 +24,12 @@ namespace Google.Protobuf.TestProtos {
             "CjNnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfaW1wb3J0X3B1YmxpY19wcm90", 
             "bzMucHJvdG8SGHByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydCIgChNQdWJsaWNJ", 
             "bXBvcnRNZXNzYWdlEgkKAWUYASABKAVCNwoYY29tLmdvb2dsZS5wcm90b2J1", 
-          "Zi50ZXN0qgIaR29vZ2xlLlByb3RvYnVmLlRlc3RQcm90b3NiBnByb3RvMw=="));
+            "Zi50ZXN0qgIaR29vZ2xlLlByb3RvYnVmLlRlc3RQcm90b3NiBnByb3RvMw=="));
       descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
-          new pbr::FileDescriptor[] {
-          });
-      internal__static_protobuf_unittest_import_PublicImportMessage__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.PublicImportMessage), descriptor.MessageTypes[0],
-              new string[] { "E", }, new string[] { });
+          new pbr::FileDescriptor[] { },
+          new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.PublicImportMessage), new[]{ "E" }, null, null, null)
+          }));
     }
     #endregion
 
@@ -44,14 +40,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<PublicImportMessage> _parser = new pb::MessageParser<PublicImportMessage>(() => new PublicImportMessage());
     public static pb::MessageParser<PublicImportMessage> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "e" };
-    private static readonly uint[] _fieldTags = new uint[] { 8 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestImportPublicProto3.Descriptor.MessageTypes[0]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestImportPublicProto3.internal__static_protobuf_unittest_import_PublicImportMessage__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;

+ 29 - 64
csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs

@@ -12,15 +12,6 @@ namespace UnitTest.Issues.TestProtos {
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
   public static partial class UnittestIssues {
 
-    #region Static variables
-    internal static pbr::FieldAccessorTable internal__static_unittest_issues_Issue307__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_unittest_issues_Issue307_NestedOnce__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_unittest_issues_Issue307_NestedOnce_NestedTwice__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_unittest_issues_NegativeEnumMessage__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_unittest_issues_DeprecatedChild__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_unittest_issues_DeprecatedFieldsMessage__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_unittest_issues_ItemField__FieldAccessorTable;
-    #endregion
     #region Descriptor
     public static pbr::FileDescriptor Descriptor {
       get { return descriptor; }
@@ -47,31 +38,16 @@ namespace UnitTest.Issues.TestProtos {
             "dGl2ZUVudW0SFgoSTkVHQVRJVkVfRU5VTV9aRVJPEAASFgoJRml2ZUJlbG93", 
             "EPv//////////wESFQoITWludXNPbmUQ////////////ASouCg5EZXByZWNh", 
             "dGVkRW51bRITCg9ERVBSRUNBVEVEX1pFUk8QABIHCgNvbmUQAUIfSAGqAhpV", 
-          "bml0VGVzdC5Jc3N1ZXMuVGVzdFByb3Rvc2IGcHJvdG8z"));
+            "bml0VGVzdC5Jc3N1ZXMuVGVzdFByb3Rvc2IGcHJvdG8z"));
       descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
-          new pbr::FileDescriptor[] {
-          });
-      internal__static_unittest_issues_Issue307__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::UnitTest.Issues.TestProtos.Issue307), descriptor.MessageTypes[0],
-              new string[] { }, new string[] { });
-      internal__static_unittest_issues_Issue307_NestedOnce__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce), descriptor.MessageTypes[0].NestedTypes[0],
-              new string[] { }, new string[] { });
-      internal__static_unittest_issues_Issue307_NestedOnce_NestedTwice__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Types.NestedTwice), descriptor.MessageTypes[0].NestedTypes[0].NestedTypes[0],
-              new string[] { }, new string[] { });
-      internal__static_unittest_issues_NegativeEnumMessage__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::UnitTest.Issues.TestProtos.NegativeEnumMessage), descriptor.MessageTypes[1],
-              new string[] { "Value", "Values", "PackedValues", }, new string[] { });
-      internal__static_unittest_issues_DeprecatedChild__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::UnitTest.Issues.TestProtos.DeprecatedChild), descriptor.MessageTypes[2],
-              new string[] { }, new string[] { });
-      internal__static_unittest_issues_DeprecatedFieldsMessage__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage), descriptor.MessageTypes[3],
-              new string[] { "PrimitiveValue", "PrimitiveArray", "MessageValue", "MessageArray", "EnumValue", "EnumArray", }, new string[] { });
-      internal__static_unittest_issues_ItemField__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::UnitTest.Issues.TestProtos.ItemField), descriptor.MessageTypes[4],
-              new string[] { "Item", }, new string[] { });
+          new pbr::FileDescriptor[] { },
+          new pbr::GeneratedCodeInfo(new[] {typeof(global::UnitTest.Issues.TestProtos.NegativeEnum), typeof(global::UnitTest.Issues.TestProtos.DeprecatedEnum), }, new pbr::GeneratedCodeInfo[] {
+            new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.Issue307), null, null, null, new pbr::GeneratedCodeInfo[] { new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce), null, null, null, new pbr::GeneratedCodeInfo[] { new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Types.NestedTwice), null, null, null, null)})}),
+            new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.NegativeEnumMessage), new[]{ "Value", "Values", "PackedValues" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.DeprecatedChild), null, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage), new[]{ "PrimitiveValue", "PrimitiveArray", "MessageValue", "MessageArray", "EnumValue", "EnumArray" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.ItemField), new[]{ "Item" }, null, null, null)
+          }));
     }
     #endregion
 
@@ -96,14 +72,12 @@ namespace UnitTest.Issues.TestProtos {
     private static readonly pb::MessageParser<Issue307> _parser = new pb::MessageParser<Issue307>(() => new Issue307());
     public static pb::MessageParser<Issue307> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] {  };
-    private static readonly uint[] _fieldTags = new uint[] {  };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestIssues.Descriptor.MessageTypes[0]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_Issue307__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -189,14 +163,12 @@ namespace UnitTest.Issues.TestProtos {
         private static readonly pb::MessageParser<NestedOnce> _parser = new pb::MessageParser<NestedOnce>(() => new NestedOnce());
         public static pb::MessageParser<NestedOnce> Parser { get { return _parser; } }
 
-        private static readonly string[] _fieldNames = new string[] {  };
-        private static readonly uint[] _fieldTags = new uint[] {  };
         public static pbr::MessageDescriptor Descriptor {
           get { return global::UnitTest.Issues.TestProtos.Issue307.Descriptor.NestedTypes[0]; }
         }
 
-        pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-          get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_Issue307_NestedOnce__FieldAccessorTable; }
+        pbr::MessageDescriptor pb::IMessage.Descriptor {
+          get { return Descriptor; }
         }
 
         private bool _frozen = false;
@@ -282,14 +254,12 @@ namespace UnitTest.Issues.TestProtos {
             private static readonly pb::MessageParser<NestedTwice> _parser = new pb::MessageParser<NestedTwice>(() => new NestedTwice());
             public static pb::MessageParser<NestedTwice> Parser { get { return _parser; } }
 
-            private static readonly string[] _fieldNames = new string[] {  };
-            private static readonly uint[] _fieldTags = new uint[] {  };
             public static pbr::MessageDescriptor Descriptor {
               get { return global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Descriptor.NestedTypes[0]; }
             }
 
-            pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-              get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_Issue307_NestedOnce_NestedTwice__FieldAccessorTable; }
+            pbr::MessageDescriptor pb::IMessage.Descriptor {
+              get { return Descriptor; }
             }
 
             private bool _frozen = false;
@@ -384,14 +354,12 @@ namespace UnitTest.Issues.TestProtos {
     private static readonly pb::MessageParser<NegativeEnumMessage> _parser = new pb::MessageParser<NegativeEnumMessage>(() => new NegativeEnumMessage());
     public static pb::MessageParser<NegativeEnumMessage> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "packed_values", "value", "values" };
-    private static readonly uint[] _fieldTags = new uint[] { 26, 8, 16 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestIssues.Descriptor.MessageTypes[1]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_NegativeEnumMessage__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -434,14 +402,16 @@ namespace UnitTest.Issues.TestProtos {
 
     public const int ValuesFieldNumber = 2;
     private static readonly pb::FieldCodec<global::UnitTest.Issues.TestProtos.NegativeEnum> _repeated_values_codec
-        = pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::UnitTest.Issues.TestProtos.NegativeEnum) x);private readonly pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum> values_ = new pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum>();
+        = pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::UnitTest.Issues.TestProtos.NegativeEnum) x);
+    private readonly pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum> values_ = new pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum>();
     public pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum> Values {
       get { return values_; }
     }
 
     public const int PackedValuesFieldNumber = 3;
     private static readonly pb::FieldCodec<global::UnitTest.Issues.TestProtos.NegativeEnum> _repeated_packedValues_codec
-        = pb::FieldCodec.ForEnum(26, x => (int) x, x => (global::UnitTest.Issues.TestProtos.NegativeEnum) x);private readonly pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum> packedValues_ = new pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum>();
+        = pb::FieldCodec.ForEnum(26, x => (int) x, x => (global::UnitTest.Issues.TestProtos.NegativeEnum) x);
+    private readonly pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum> packedValues_ = new pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum>();
     public pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum> PackedValues {
       get { return packedValues_; }
     }
@@ -541,14 +511,12 @@ namespace UnitTest.Issues.TestProtos {
     private static readonly pb::MessageParser<DeprecatedChild> _parser = new pb::MessageParser<DeprecatedChild>(() => new DeprecatedChild());
     public static pb::MessageParser<DeprecatedChild> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] {  };
-    private static readonly uint[] _fieldTags = new uint[] {  };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestIssues.Descriptor.MessageTypes[2]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_DeprecatedChild__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -633,14 +601,12 @@ namespace UnitTest.Issues.TestProtos {
     private static readonly pb::MessageParser<DeprecatedFieldsMessage> _parser = new pb::MessageParser<DeprecatedFieldsMessage>(() => new DeprecatedFieldsMessage());
     public static pb::MessageParser<DeprecatedFieldsMessage> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "EnumArray", "EnumValue", "MessageArray", "MessageValue", "PrimitiveArray", "PrimitiveValue" };
-    private static readonly uint[] _fieldTags = new uint[] { 50, 40, 34, 26, 18, 8 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestIssues.Descriptor.MessageTypes[3]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_DeprecatedFieldsMessage__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -729,7 +695,8 @@ namespace UnitTest.Issues.TestProtos {
 
     public const int EnumArrayFieldNumber = 6;
     private static readonly pb::FieldCodec<global::UnitTest.Issues.TestProtos.DeprecatedEnum> _repeated_enumArray_codec
-        = pb::FieldCodec.ForEnum(50, x => (int) x, x => (global::UnitTest.Issues.TestProtos.DeprecatedEnum) x);private readonly pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedEnum> enumArray_ = new pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedEnum>();
+        = pb::FieldCodec.ForEnum(50, x => (int) x, x => (global::UnitTest.Issues.TestProtos.DeprecatedEnum) x);
+    private readonly pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedEnum> enumArray_ = new pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedEnum>();
     [global::System.ObsoleteAttribute()]
     public pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedEnum> EnumArray {
       get { return enumArray_; }
@@ -877,14 +844,12 @@ namespace UnitTest.Issues.TestProtos {
     private static readonly pb::MessageParser<ItemField> _parser = new pb::MessageParser<ItemField>(() => new ItemField());
     public static pb::MessageParser<ItemField> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "item" };
-    private static readonly uint[] _fieldTags = new uint[] { 8 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestIssues.Descriptor.MessageTypes[4]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_ItemField__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;

+ 119 - 292
csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs

@@ -12,43 +12,6 @@ namespace Google.Protobuf.TestProtos {
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
   public static partial class UnittestProto3 {
 
-    #region Static variables
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_TestAllTypes__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_TestAllTypes_NestedMessage__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_NestedTestAllTypes__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_TestDeprecatedFields__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_ForeignMessage__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_TestReservedFields__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_TestForeignNested__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_TestReallyLargeTagNumber__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_TestRecursiveMessage__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_TestMutualRecursionA__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_TestMutualRecursionB__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_TestCamelCaseFieldNames__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_TestFieldOrderings__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_TestFieldOrderings_NestedMessage__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_SparseEnumMessage__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_OneString__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_MoreString__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_OneBytes__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_MoreBytes__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_Int32Message__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_Uint32Message__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_Int64Message__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_Uint64Message__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_BoolMessage__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_TestOneof__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_TestPackedTypes__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_TestUnpackedTypes__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_TestRepeatedScalarDifferentTagSizes__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_TestCommentInjectionMessage__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_FooRequest__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_FooResponse__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_FooClientMessage__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_FooServerMessage__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_BarRequest__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_BarResponse__FieldAccessorTable;
-    #endregion
     #region Descriptor
     public static pbr::FileDescriptor Descriptor {
       get { return descriptor; }
@@ -184,116 +147,44 @@ namespace Google.Protobuf.TestProtos {
             "cXVlc3QaHi5wcm90b2J1Zl91bml0dGVzdC5Gb29SZXNwb25zZRJECgNCYXIS", 
             "HS5wcm90b2J1Zl91bml0dGVzdC5CYXJSZXF1ZXN0Gh4ucHJvdG9idWZfdW5p", 
             "dHRlc3QuQmFyUmVzcG9uc2VCOkINVW5pdHRlc3RQcm90b0gBgAEBiAEBkAEB", 
-          "+AEBqgIaR29vZ2xlLlByb3RvYnVmLlRlc3RQcm90b3NiBnByb3RvMw=="));
+            "+AEBqgIaR29vZ2xlLlByb3RvYnVmLlRlc3RQcm90b3NiBnByb3RvMw=="));
       descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
-          new pbr::FileDescriptor[] {
-          global::Google.Protobuf.TestProtos.UnittestImportProto3.Descriptor, 
-          });
-      internal__static_protobuf_unittest_TestAllTypes__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestAllTypes), descriptor.MessageTypes[0],
-              new string[] { "SingleInt32", "SingleInt64", "SingleUint32", "SingleUint64", "SingleSint32", "SingleSint64", "SingleFixed32", "SingleFixed64", "SingleSfixed32", "SingleSfixed64", "SingleFloat", "SingleDouble", "SingleBool", "SingleString", "SingleBytes", "SingleNestedMessage", "SingleForeignMessage", "SingleImportMessage", "SingleNestedEnum", "SingleForeignEnum", "SingleImportEnum", "SinglePublicImportMessage", "RepeatedInt32", "RepeatedInt64", "RepeatedUint32", "RepeatedUint64", "RepeatedSint32", "RepeatedSint64", "RepeatedFixed32", "RepeatedFixed64", "RepeatedSfixed32", "RepeatedSfixed64", "RepeatedFloat", "RepeatedDouble", "RepeatedBool", "RepeatedString", "RepeatedBytes", "RepeatedNestedMessage", "RepeatedForeignMessage", "RepeatedImportMessage", "RepeatedNestedEnum", "RepeatedForeignEnum", "RepeatedImportEnum", "RepeatedPublicImportMessage", "OneofUint32", "OneofNestedMessage", "OneofString", "OneofBytes", }, new string[] { "OneofField", });
-      internal__static_protobuf_unittest_TestAllTypes_NestedMessage__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage), descriptor.MessageTypes[0].NestedTypes[0],
-              new string[] { "Bb", }, new string[] { });
-      internal__static_protobuf_unittest_NestedTestAllTypes__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.NestedTestAllTypes), descriptor.MessageTypes[1],
-              new string[] { "Child", "Payload", "RepeatedChild", }, new string[] { });
-      internal__static_protobuf_unittest_TestDeprecatedFields__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestDeprecatedFields), descriptor.MessageTypes[2],
-              new string[] { "DeprecatedInt32", }, new string[] { });
-      internal__static_protobuf_unittest_ForeignMessage__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.ForeignMessage), descriptor.MessageTypes[3],
-              new string[] { "C", }, new string[] { });
-      internal__static_protobuf_unittest_TestReservedFields__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestReservedFields), descriptor.MessageTypes[4],
-              new string[] { }, new string[] { });
-      internal__static_protobuf_unittest_TestForeignNested__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestForeignNested), descriptor.MessageTypes[5],
-              new string[] { "ForeignNested", }, new string[] { });
-      internal__static_protobuf_unittest_TestReallyLargeTagNumber__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestReallyLargeTagNumber), descriptor.MessageTypes[6],
-              new string[] { "A", "Bb", }, new string[] { });
-      internal__static_protobuf_unittest_TestRecursiveMessage__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestRecursiveMessage), descriptor.MessageTypes[7],
-              new string[] { "A", "I", }, new string[] { });
-      internal__static_protobuf_unittest_TestMutualRecursionA__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestMutualRecursionA), descriptor.MessageTypes[8],
-              new string[] { "Bb", }, new string[] { });
-      internal__static_protobuf_unittest_TestMutualRecursionB__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestMutualRecursionB), descriptor.MessageTypes[9],
-              new string[] { "A", "OptionalInt32", }, new string[] { });
-      internal__static_protobuf_unittest_TestCamelCaseFieldNames__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestCamelCaseFieldNames), descriptor.MessageTypes[10],
-              new string[] { "PrimitiveField", "StringField", "EnumField", "MessageField", "RepeatedPrimitiveField", "RepeatedStringField", "RepeatedEnumField", "RepeatedMessageField", }, new string[] { });
-      internal__static_protobuf_unittest_TestFieldOrderings__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestFieldOrderings), descriptor.MessageTypes[11],
-              new string[] { "MyString", "MyInt", "MyFloat", "SingleNestedMessage", }, new string[] { });
-      internal__static_protobuf_unittest_TestFieldOrderings_NestedMessage__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage), descriptor.MessageTypes[11].NestedTypes[0],
-              new string[] { "Oo", "Bb", }, new string[] { });
-      internal__static_protobuf_unittest_SparseEnumMessage__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.SparseEnumMessage), descriptor.MessageTypes[12],
-              new string[] { "SparseEnum", }, new string[] { });
-      internal__static_protobuf_unittest_OneString__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.OneString), descriptor.MessageTypes[13],
-              new string[] { "Data", }, new string[] { });
-      internal__static_protobuf_unittest_MoreString__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.MoreString), descriptor.MessageTypes[14],
-              new string[] { "Data", }, new string[] { });
-      internal__static_protobuf_unittest_OneBytes__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.OneBytes), descriptor.MessageTypes[15],
-              new string[] { "Data", }, new string[] { });
-      internal__static_protobuf_unittest_MoreBytes__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.MoreBytes), descriptor.MessageTypes[16],
-              new string[] { "Data", }, new string[] { });
-      internal__static_protobuf_unittest_Int32Message__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.Int32Message), descriptor.MessageTypes[17],
-              new string[] { "Data", }, new string[] { });
-      internal__static_protobuf_unittest_Uint32Message__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.Uint32Message), descriptor.MessageTypes[18],
-              new string[] { "Data", }, new string[] { });
-      internal__static_protobuf_unittest_Int64Message__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.Int64Message), descriptor.MessageTypes[19],
-              new string[] { "Data", }, new string[] { });
-      internal__static_protobuf_unittest_Uint64Message__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.Uint64Message), descriptor.MessageTypes[20],
-              new string[] { "Data", }, new string[] { });
-      internal__static_protobuf_unittest_BoolMessage__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.BoolMessage), descriptor.MessageTypes[21],
-              new string[] { "Data", }, new string[] { });
-      internal__static_protobuf_unittest_TestOneof__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestOneof), descriptor.MessageTypes[22],
-              new string[] { "FooInt", "FooString", "FooMessage", }, new string[] { "Foo", });
-      internal__static_protobuf_unittest_TestPackedTypes__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestPackedTypes), descriptor.MessageTypes[23],
-              new string[] { "PackedInt32", "PackedInt64", "PackedUint32", "PackedUint64", "PackedSint32", "PackedSint64", "PackedFixed32", "PackedFixed64", "PackedSfixed32", "PackedSfixed64", "PackedFloat", "PackedDouble", "PackedBool", "PackedEnum", }, new string[] { });
-      internal__static_protobuf_unittest_TestUnpackedTypes__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestUnpackedTypes), descriptor.MessageTypes[24],
-              new string[] { "UnpackedInt32", "UnpackedInt64", "UnpackedUint32", "UnpackedUint64", "UnpackedSint32", "UnpackedSint64", "UnpackedFixed32", "UnpackedFixed64", "UnpackedSfixed32", "UnpackedSfixed64", "UnpackedFloat", "UnpackedDouble", "UnpackedBool", "UnpackedEnum", }, new string[] { });
-      internal__static_protobuf_unittest_TestRepeatedScalarDifferentTagSizes__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestRepeatedScalarDifferentTagSizes), descriptor.MessageTypes[25],
-              new string[] { "RepeatedFixed32", "RepeatedInt32", "RepeatedFixed64", "RepeatedInt64", "RepeatedFloat", "RepeatedUint64", }, new string[] { });
-      internal__static_protobuf_unittest_TestCommentInjectionMessage__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestCommentInjectionMessage), descriptor.MessageTypes[26],
-              new string[] { "A", }, new string[] { });
-      internal__static_protobuf_unittest_FooRequest__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.FooRequest), descriptor.MessageTypes[27],
-              new string[] { }, new string[] { });
-      internal__static_protobuf_unittest_FooResponse__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.FooResponse), descriptor.MessageTypes[28],
-              new string[] { }, new string[] { });
-      internal__static_protobuf_unittest_FooClientMessage__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.FooClientMessage), descriptor.MessageTypes[29],
-              new string[] { }, new string[] { });
-      internal__static_protobuf_unittest_FooServerMessage__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.FooServerMessage), descriptor.MessageTypes[30],
-              new string[] { }, new string[] { });
-      internal__static_protobuf_unittest_BarRequest__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.BarRequest), descriptor.MessageTypes[31],
-              new string[] { }, new string[] { });
-      internal__static_protobuf_unittest_BarResponse__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.BarResponse), descriptor.MessageTypes[32],
-              new string[] { }, new string[] { });
+          new pbr::FileDescriptor[] { global::Google.Protobuf.TestProtos.UnittestImportProto3.Descriptor, },
+          new pbr::GeneratedCodeInfo(new[] {typeof(global::Google.Protobuf.TestProtos.ForeignEnum), typeof(global::Google.Protobuf.TestProtos.TestEnumWithDupValue), typeof(global::Google.Protobuf.TestProtos.TestSparseEnum), }, new pbr::GeneratedCodeInfo[] {
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestAllTypes), new[]{ "SingleInt32", "SingleInt64", "SingleUint32", "SingleUint64", "SingleSint32", "SingleSint64", "SingleFixed32", "SingleFixed64", "SingleSfixed32", "SingleSfixed64", "SingleFloat", "SingleDouble", "SingleBool", "SingleString", "SingleBytes", "SingleNestedMessage", "SingleForeignMessage", "SingleImportMessage", "SingleNestedEnum", "SingleForeignEnum", "SingleImportEnum", "SinglePublicImportMessage", "RepeatedInt32", "RepeatedInt64", "RepeatedUint32", "RepeatedUint64", "RepeatedSint32", "RepeatedSint64", "RepeatedFixed32", "RepeatedFixed64", "RepeatedSfixed32", "RepeatedSfixed64", "RepeatedFloat", "RepeatedDouble", "RepeatedBool", "RepeatedString", "RepeatedBytes", "RepeatedNestedMessage", "RepeatedForeignMessage", "RepeatedImportMessage", "RepeatedNestedEnum", "RepeatedForeignEnum", "RepeatedImportEnum", "RepeatedPublicImportMessage", "OneofUint32", "OneofNestedMessage", "OneofString", "OneofBytes" }, new[]{ "OneofField" }, new[]{ typeof(global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum) }, new pbr::GeneratedCodeInfo[] { new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage), new[]{ "Bb" }, null, null, null)}),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.NestedTestAllTypes), new[]{ "Child", "Payload", "RepeatedChild" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestDeprecatedFields), new[]{ "DeprecatedInt32" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.ForeignMessage), new[]{ "C" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestReservedFields), null, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestForeignNested), new[]{ "ForeignNested" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestReallyLargeTagNumber), new[]{ "A", "Bb" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestRecursiveMessage), new[]{ "A", "I" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestMutualRecursionA), new[]{ "Bb" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestMutualRecursionB), new[]{ "A", "OptionalInt32" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestCamelCaseFieldNames), new[]{ "PrimitiveField", "StringField", "EnumField", "MessageField", "RepeatedPrimitiveField", "RepeatedStringField", "RepeatedEnumField", "RepeatedMessageField" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestFieldOrderings), new[]{ "MyString", "MyInt", "MyFloat", "SingleNestedMessage" }, null, null, new pbr::GeneratedCodeInfo[] { new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage), new[]{ "Oo", "Bb" }, null, null, null)}),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.SparseEnumMessage), new[]{ "SparseEnum" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.OneString), new[]{ "Data" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.MoreString), new[]{ "Data" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.OneBytes), new[]{ "Data" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.MoreBytes), new[]{ "Data" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.Int32Message), new[]{ "Data" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.Uint32Message), new[]{ "Data" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.Int64Message), new[]{ "Data" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.Uint64Message), new[]{ "Data" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.BoolMessage), new[]{ "Data" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestOneof), new[]{ "FooInt", "FooString", "FooMessage" }, new[]{ "Foo" }, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestPackedTypes), new[]{ "PackedInt32", "PackedInt64", "PackedUint32", "PackedUint64", "PackedSint32", "PackedSint64", "PackedFixed32", "PackedFixed64", "PackedSfixed32", "PackedSfixed64", "PackedFloat", "PackedDouble", "PackedBool", "PackedEnum" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestUnpackedTypes), new[]{ "UnpackedInt32", "UnpackedInt64", "UnpackedUint32", "UnpackedUint64", "UnpackedSint32", "UnpackedSint64", "UnpackedFixed32", "UnpackedFixed64", "UnpackedSfixed32", "UnpackedSfixed64", "UnpackedFloat", "UnpackedDouble", "UnpackedBool", "UnpackedEnum" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestRepeatedScalarDifferentTagSizes), new[]{ "RepeatedFixed32", "RepeatedInt32", "RepeatedFixed64", "RepeatedInt64", "RepeatedFloat", "RepeatedUint64" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestCommentInjectionMessage), new[]{ "A" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.FooRequest), null, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.FooResponse), null, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.FooClientMessage), null, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.FooServerMessage), null, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.BarRequest), null, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.BarResponse), null, null, null, null)
+          }));
     }
     #endregion
 
@@ -333,14 +224,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<TestAllTypes> _parser = new pb::MessageParser<TestAllTypes>(() => new TestAllTypes());
     public static pb::MessageParser<TestAllTypes> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "oneof_bytes", "oneof_nested_message", "oneof_string", "oneof_uint32", "repeated_bool", "repeated_bytes", "repeated_double", "repeated_fixed32", "repeated_fixed64", "repeated_float", "repeated_foreign_enum", "repeated_foreign_message", "repeated_import_enum", "repeated_import_message", "repeated_int32", "repeated_int64", "repeated_nested_enum", "repeated_nested_message", "repeated_public_import_message", "repeated_sfixed32", "repeated_sfixed64", "repeated_sint32", "repeated_sint64", "repeated_string", "repeated_uint32", "repeated_uint64", "single_bool", "single_bytes", "single_double", "single_fixed32", "single_fixed64", "single_float", "single_foreign_enum", "single_foreign_message", "single_import_enum", "single_import_message", "single_int32", "single_int64", "single_nested_enum", "single_nested_message", "single_public_import_message", "single_sfixed32", "single_sfixed64", "single_sint32", "single_sint64", "single_string", "single_uint32", "single_uint64" };
-    private static readonly uint[] _fieldTags = new uint[] { 914, 898, 906, 888, 346, 362, 338, 298, 306, 330, 418, 394, 426, 402, 250, 258, 410, 386, 434, 314, 322, 282, 290, 354, 266, 274, 104, 122, 97, 61, 65, 93, 176, 154, 184, 162, 8, 16, 168, 146, 210, 77, 81, 40, 48, 114, 24, 32 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[0]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestAllTypes__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -818,21 +707,24 @@ namespace Google.Protobuf.TestProtos {
 
     public const int RepeatedNestedEnumFieldNumber = 51;
     private static readonly pb::FieldCodec<global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum> _repeated_repeatedNestedEnum_codec
-        = pb::FieldCodec.ForEnum(410, x => (int) x, x => (global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum) x);private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum> repeatedNestedEnum_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum>();
+        = pb::FieldCodec.ForEnum(410, x => (int) x, x => (global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum) x);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum> repeatedNestedEnum_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum>();
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum> RepeatedNestedEnum {
       get { return repeatedNestedEnum_; }
     }
 
     public const int RepeatedForeignEnumFieldNumber = 52;
     private static readonly pb::FieldCodec<global::Google.Protobuf.TestProtos.ForeignEnum> _repeated_repeatedForeignEnum_codec
-        = pb::FieldCodec.ForEnum(418, x => (int) x, x => (global::Google.Protobuf.TestProtos.ForeignEnum) x);private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> repeatedForeignEnum_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum>();
+        = pb::FieldCodec.ForEnum(418, x => (int) x, x => (global::Google.Protobuf.TestProtos.ForeignEnum) x);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> repeatedForeignEnum_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum>();
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> RepeatedForeignEnum {
       get { return repeatedForeignEnum_; }
     }
 
     public const int RepeatedImportEnumFieldNumber = 53;
     private static readonly pb::FieldCodec<global::Google.Protobuf.TestProtos.ImportEnum> _repeated_repeatedImportEnum_codec
-        = pb::FieldCodec.ForEnum(426, x => (int) x, x => (global::Google.Protobuf.TestProtos.ImportEnum) x);private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.ImportEnum> repeatedImportEnum_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.ImportEnum>();
+        = pb::FieldCodec.ForEnum(426, x => (int) x, x => (global::Google.Protobuf.TestProtos.ImportEnum) x);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.ImportEnum> repeatedImportEnum_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.ImportEnum>();
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.ImportEnum> RepeatedImportEnum {
       get { return repeatedImportEnum_; }
     }
@@ -1634,14 +1526,12 @@ namespace Google.Protobuf.TestProtos {
         private static readonly pb::MessageParser<NestedMessage> _parser = new pb::MessageParser<NestedMessage>(() => new NestedMessage());
         public static pb::MessageParser<NestedMessage> Parser { get { return _parser; } }
 
-        private static readonly string[] _fieldNames = new string[] { "bb" };
-        private static readonly uint[] _fieldTags = new uint[] { 8 };
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.TestProtos.TestAllTypes.Descriptor.NestedTypes[0]; }
         }
 
-        pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-          get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestAllTypes_NestedMessage__FieldAccessorTable; }
+        pbr::MessageDescriptor pb::IMessage.Descriptor {
+          get { return Descriptor; }
         }
 
         private bool _frozen = false;
@@ -1758,14 +1648,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<NestedTestAllTypes> _parser = new pb::MessageParser<NestedTestAllTypes>(() => new NestedTestAllTypes());
     public static pb::MessageParser<NestedTestAllTypes> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "child", "payload", "repeated_child" };
-    private static readonly uint[] _fieldTags = new uint[] { 10, 18, 26 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[1]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_NestedTestAllTypes__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -1937,14 +1825,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<TestDeprecatedFields> _parser = new pb::MessageParser<TestDeprecatedFields>(() => new TestDeprecatedFields());
     public static pb::MessageParser<TestDeprecatedFields> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "deprecated_int32" };
-    private static readonly uint[] _fieldTags = new uint[] { 8 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[2]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestDeprecatedFields__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -2057,14 +1943,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<ForeignMessage> _parser = new pb::MessageParser<ForeignMessage>(() => new ForeignMessage());
     public static pb::MessageParser<ForeignMessage> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "c" };
-    private static readonly uint[] _fieldTags = new uint[] { 8 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[3]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_ForeignMessage__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -2176,14 +2060,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<TestReservedFields> _parser = new pb::MessageParser<TestReservedFields>(() => new TestReservedFields());
     public static pb::MessageParser<TestReservedFields> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] {  };
-    private static readonly uint[] _fieldTags = new uint[] {  };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[4]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestReservedFields__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -2268,14 +2150,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<TestForeignNested> _parser = new pb::MessageParser<TestForeignNested>(() => new TestForeignNested());
     public static pb::MessageParser<TestForeignNested> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "foreign_nested" };
-    private static readonly uint[] _fieldTags = new uint[] { 10 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[5]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestForeignNested__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -2394,14 +2274,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<TestReallyLargeTagNumber> _parser = new pb::MessageParser<TestReallyLargeTagNumber>(() => new TestReallyLargeTagNumber());
     public static pb::MessageParser<TestReallyLargeTagNumber> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "a", "bb" };
-    private static readonly uint[] _fieldTags = new uint[] { 8, 2147483640 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[6]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestReallyLargeTagNumber__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -2540,14 +2418,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<TestRecursiveMessage> _parser = new pb::MessageParser<TestRecursiveMessage>(() => new TestRecursiveMessage());
     public static pb::MessageParser<TestRecursiveMessage> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "a", "i" };
-    private static readonly uint[] _fieldTags = new uint[] { 10, 16 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[7]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestRecursiveMessage__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -2693,14 +2569,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<TestMutualRecursionA> _parser = new pb::MessageParser<TestMutualRecursionA>(() => new TestMutualRecursionA());
     public static pb::MessageParser<TestMutualRecursionA> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "bb" };
-    private static readonly uint[] _fieldTags = new uint[] { 10 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[8]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestMutualRecursionA__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -2819,14 +2693,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<TestMutualRecursionB> _parser = new pb::MessageParser<TestMutualRecursionB>(() => new TestMutualRecursionB());
     public static pb::MessageParser<TestMutualRecursionB> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "a", "optional_int32" };
-    private static readonly uint[] _fieldTags = new uint[] { 10, 16 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[9]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestMutualRecursionB__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -2972,14 +2844,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<TestCamelCaseFieldNames> _parser = new pb::MessageParser<TestCamelCaseFieldNames>(() => new TestCamelCaseFieldNames());
     public static pb::MessageParser<TestCamelCaseFieldNames> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "EnumField", "MessageField", "PrimitiveField", "RepeatedEnumField", "RepeatedMessageField", "RepeatedPrimitiveField", "RepeatedStringField", "StringField" };
-    private static readonly uint[] _fieldTags = new uint[] { 24, 34, 8, 74, 82, 58, 66, 18 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[10]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestCamelCaseFieldNames__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -3076,7 +2946,8 @@ namespace Google.Protobuf.TestProtos {
 
     public const int RepeatedEnumFieldFieldNumber = 9;
     private static readonly pb::FieldCodec<global::Google.Protobuf.TestProtos.ForeignEnum> _repeated_repeatedEnumField_codec
-        = pb::FieldCodec.ForEnum(74, x => (int) x, x => (global::Google.Protobuf.TestProtos.ForeignEnum) x);private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> repeatedEnumField_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum>();
+        = pb::FieldCodec.ForEnum(74, x => (int) x, x => (global::Google.Protobuf.TestProtos.ForeignEnum) x);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> repeatedEnumField_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum>();
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> RepeatedEnumField {
       get { return repeatedEnumField_; }
     }
@@ -3256,14 +3127,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<TestFieldOrderings> _parser = new pb::MessageParser<TestFieldOrderings>(() => new TestFieldOrderings());
     public static pb::MessageParser<TestFieldOrderings> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "my_float", "my_int", "my_string", "single_nested_message" };
-    private static readonly uint[] _fieldTags = new uint[] { 813, 8, 90, 1602 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[11]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestFieldOrderings__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -3464,14 +3333,12 @@ namespace Google.Protobuf.TestProtos {
         private static readonly pb::MessageParser<NestedMessage> _parser = new pb::MessageParser<NestedMessage>(() => new NestedMessage());
         public static pb::MessageParser<NestedMessage> Parser { get { return _parser; } }
 
-        private static readonly string[] _fieldNames = new string[] { "bb", "oo" };
-        private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.TestProtos.TestFieldOrderings.Descriptor.NestedTypes[0]; }
         }
 
-        pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-          get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestFieldOrderings_NestedMessage__FieldAccessorTable; }
+        pbr::MessageDescriptor pb::IMessage.Descriptor {
+          get { return Descriptor; }
         }
 
         private bool _frozen = false;
@@ -3615,14 +3482,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<SparseEnumMessage> _parser = new pb::MessageParser<SparseEnumMessage>(() => new SparseEnumMessage());
     public static pb::MessageParser<SparseEnumMessage> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "sparse_enum" };
-    private static readonly uint[] _fieldTags = new uint[] { 8 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[12]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_SparseEnumMessage__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -3734,14 +3599,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<OneString> _parser = new pb::MessageParser<OneString>(() => new OneString());
     public static pb::MessageParser<OneString> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "data" };
-    private static readonly uint[] _fieldTags = new uint[] { 10 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[13]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_OneString__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -3853,14 +3716,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<MoreString> _parser = new pb::MessageParser<MoreString>(() => new MoreString());
     public static pb::MessageParser<MoreString> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "data" };
-    private static readonly uint[] _fieldTags = new uint[] { 10 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[14]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_MoreString__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -3964,14 +3825,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<OneBytes> _parser = new pb::MessageParser<OneBytes>(() => new OneBytes());
     public static pb::MessageParser<OneBytes> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "data" };
-    private static readonly uint[] _fieldTags = new uint[] { 10 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[15]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_OneBytes__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -4083,14 +3942,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<MoreBytes> _parser = new pb::MessageParser<MoreBytes>(() => new MoreBytes());
     public static pb::MessageParser<MoreBytes> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "data" };
-    private static readonly uint[] _fieldTags = new uint[] { 10 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[16]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_MoreBytes__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -4202,14 +4059,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<Int32Message> _parser = new pb::MessageParser<Int32Message>(() => new Int32Message());
     public static pb::MessageParser<Int32Message> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "data" };
-    private static readonly uint[] _fieldTags = new uint[] { 8 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[17]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_Int32Message__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -4321,14 +4176,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<Uint32Message> _parser = new pb::MessageParser<Uint32Message>(() => new Uint32Message());
     public static pb::MessageParser<Uint32Message> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "data" };
-    private static readonly uint[] _fieldTags = new uint[] { 8 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[18]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_Uint32Message__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -4440,14 +4293,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<Int64Message> _parser = new pb::MessageParser<Int64Message>(() => new Int64Message());
     public static pb::MessageParser<Int64Message> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "data" };
-    private static readonly uint[] _fieldTags = new uint[] { 8 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[19]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_Int64Message__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -4559,14 +4410,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<Uint64Message> _parser = new pb::MessageParser<Uint64Message>(() => new Uint64Message());
     public static pb::MessageParser<Uint64Message> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "data" };
-    private static readonly uint[] _fieldTags = new uint[] { 8 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[20]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_Uint64Message__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -4678,14 +4527,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<BoolMessage> _parser = new pb::MessageParser<BoolMessage>(() => new BoolMessage());
     public static pb::MessageParser<BoolMessage> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "data" };
-    private static readonly uint[] _fieldTags = new uint[] { 8 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[21]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_BoolMessage__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -4797,14 +4644,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<TestOneof> _parser = new pb::MessageParser<TestOneof>(() => new TestOneof());
     public static pb::MessageParser<TestOneof> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "foo_int", "foo_message", "foo_string" };
-    private static readonly uint[] _fieldTags = new uint[] { 8, 26, 18 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[22]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestOneof__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -5006,14 +4851,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<TestPackedTypes> _parser = new pb::MessageParser<TestPackedTypes>(() => new TestPackedTypes());
     public static pb::MessageParser<TestPackedTypes> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "packed_bool", "packed_double", "packed_enum", "packed_fixed32", "packed_fixed64", "packed_float", "packed_int32", "packed_int64", "packed_sfixed32", "packed_sfixed64", "packed_sint32", "packed_sint64", "packed_uint32", "packed_uint64" };
-    private static readonly uint[] _fieldTags = new uint[] { 818, 810, 826, 770, 778, 802, 722, 730, 786, 794, 754, 762, 738, 746 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[23]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestPackedTypes__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -5173,7 +5016,8 @@ namespace Google.Protobuf.TestProtos {
 
     public const int PackedEnumFieldNumber = 103;
     private static readonly pb::FieldCodec<global::Google.Protobuf.TestProtos.ForeignEnum> _repeated_packedEnum_codec
-        = pb::FieldCodec.ForEnum(826, x => (int) x, x => (global::Google.Protobuf.TestProtos.ForeignEnum) x);private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> packedEnum_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum>();
+        = pb::FieldCodec.ForEnum(826, x => (int) x, x => (global::Google.Protobuf.TestProtos.ForeignEnum) x);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> packedEnum_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum>();
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> PackedEnum {
       get { return packedEnum_; }
     }
@@ -5377,14 +5221,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<TestUnpackedTypes> _parser = new pb::MessageParser<TestUnpackedTypes>(() => new TestUnpackedTypes());
     public static pb::MessageParser<TestUnpackedTypes> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "unpacked_bool", "unpacked_double", "unpacked_enum", "unpacked_fixed32", "unpacked_fixed64", "unpacked_float", "unpacked_int32", "unpacked_int64", "unpacked_sfixed32", "unpacked_sfixed64", "unpacked_sint32", "unpacked_sint64", "unpacked_uint32", "unpacked_uint64" };
-    private static readonly uint[] _fieldTags = new uint[] { 816, 809, 824, 773, 777, 805, 720, 728, 789, 793, 752, 760, 736, 744 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[24]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestUnpackedTypes__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -5544,7 +5386,8 @@ namespace Google.Protobuf.TestProtos {
 
     public const int UnpackedEnumFieldNumber = 103;
     private static readonly pb::FieldCodec<global::Google.Protobuf.TestProtos.ForeignEnum> _repeated_unpackedEnum_codec
-        = pb::FieldCodec.ForEnum(824, x => (int) x, x => (global::Google.Protobuf.TestProtos.ForeignEnum) x);private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> unpackedEnum_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum>();
+        = pb::FieldCodec.ForEnum(824, x => (int) x, x => (global::Google.Protobuf.TestProtos.ForeignEnum) x);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> unpackedEnum_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum>();
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> UnpackedEnum {
       get { return unpackedEnum_; }
     }
@@ -5748,14 +5591,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<TestRepeatedScalarDifferentTagSizes> _parser = new pb::MessageParser<TestRepeatedScalarDifferentTagSizes>(() => new TestRepeatedScalarDifferentTagSizes());
     public static pb::MessageParser<TestRepeatedScalarDifferentTagSizes> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "repeated_fixed32", "repeated_fixed64", "repeated_float", "repeated_int32", "repeated_int64", "repeated_uint64" };
-    private static readonly uint[] _fieldTags = new uint[] { 98, 16370, 2097138, 106, 16378, 2097146 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[25]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestRepeatedScalarDifferentTagSizes__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -5960,14 +5801,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<TestCommentInjectionMessage> _parser = new pb::MessageParser<TestCommentInjectionMessage>(() => new TestCommentInjectionMessage());
     public static pb::MessageParser<TestCommentInjectionMessage> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "a" };
-    private static readonly uint[] _fieldTags = new uint[] { 10 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[26]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestCommentInjectionMessage__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -6079,14 +5918,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<FooRequest> _parser = new pb::MessageParser<FooRequest>(() => new FooRequest());
     public static pb::MessageParser<FooRequest> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] {  };
-    private static readonly uint[] _fieldTags = new uint[] {  };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[27]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_FooRequest__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -6171,14 +6008,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<FooResponse> _parser = new pb::MessageParser<FooResponse>(() => new FooResponse());
     public static pb::MessageParser<FooResponse> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] {  };
-    private static readonly uint[] _fieldTags = new uint[] {  };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[28]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_FooResponse__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -6263,14 +6098,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<FooClientMessage> _parser = new pb::MessageParser<FooClientMessage>(() => new FooClientMessage());
     public static pb::MessageParser<FooClientMessage> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] {  };
-    private static readonly uint[] _fieldTags = new uint[] {  };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[29]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_FooClientMessage__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -6355,14 +6188,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<FooServerMessage> _parser = new pb::MessageParser<FooServerMessage>(() => new FooServerMessage());
     public static pb::MessageParser<FooServerMessage> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] {  };
-    private static readonly uint[] _fieldTags = new uint[] {  };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[30]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_FooServerMessage__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -6447,14 +6278,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<BarRequest> _parser = new pb::MessageParser<BarRequest>(() => new BarRequest());
     public static pb::MessageParser<BarRequest> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] {  };
-    private static readonly uint[] _fieldTags = new uint[] {  };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[31]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_BarRequest__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -6539,14 +6368,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<BarResponse> _parser = new pb::MessageParser<BarResponse>(() => new BarResponse());
     public static pb::MessageParser<BarResponse> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] {  };
-    private static readonly uint[] _fieldTags = new uint[] {  };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[32]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_BarResponse__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;

+ 16 - 47
csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs

@@ -12,12 +12,6 @@ namespace Google.Protobuf.TestProtos {
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
   public static partial class UnittestWellKnownTypes {
 
-    #region Static variables
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_TestWellKnownTypes__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_RepeatedWellKnownTypes__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_OneofWellKnownTypes__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_protobuf_unittest_MapWellKnownTypes__FieldAccessorTable;
-    #endregion
     #region Descriptor
     public static pbr::FileDescriptor Descriptor {
       get { return descriptor; }
@@ -162,32 +156,15 @@ namespace Google.Protobuf.TestProtos {
             "AjgBGk4KD0J5dGVzRmllbGRFbnRyeRILCgNrZXkYASABKAUSKgoFdmFsdWUY", 
             "AiABKAsyGy5nb29nbGUucHJvdG9idWYuQnl0ZXNWYWx1ZToCOAFCOQoYY29t", 
             "Lmdvb2dsZS5wcm90b2J1Zi50ZXN0UAGqAhpHb29nbGUuUHJvdG9idWYuVGVz", 
-          "dFByb3Rvc2IGcHJvdG8z"));
+            "dFByb3Rvc2IGcHJvdG8z"));
       descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
-          new pbr::FileDescriptor[] {
-          global::Google.Protobuf.WellKnownTypes.Proto.Any.Descriptor, 
-          global::Google.Protobuf.WellKnownTypes.Proto.Api.Descriptor, 
-          global::Google.Protobuf.WellKnownTypes.Proto.Duration.Descriptor, 
-          global::Google.Protobuf.WellKnownTypes.Proto.Empty.Descriptor, 
-          global::Google.Protobuf.WellKnownTypes.Proto.FieldMask.Descriptor, 
-          global::Google.Protobuf.WellKnownTypes.Proto.SourceContext.Descriptor, 
-          global::Google.Protobuf.WellKnownTypes.Proto.Struct.Descriptor, 
-          global::Google.Protobuf.WellKnownTypes.Proto.Timestamp.Descriptor, 
-          global::Google.Protobuf.WellKnownTypes.Proto.Type.Descriptor, 
-          global::Google.Protobuf.WellKnownTypes.Wrappers.Descriptor, 
-          });
-      internal__static_protobuf_unittest_TestWellKnownTypes__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestWellKnownTypes), descriptor.MessageTypes[0],
-              new string[] { "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField", }, new string[] { });
-      internal__static_protobuf_unittest_RepeatedWellKnownTypes__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.RepeatedWellKnownTypes), descriptor.MessageTypes[1],
-              new string[] { "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField", }, new string[] { });
-      internal__static_protobuf_unittest_OneofWellKnownTypes__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.OneofWellKnownTypes), descriptor.MessageTypes[2],
-              new string[] { "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField", }, new string[] { "OneofField", });
-      internal__static_protobuf_unittest_MapWellKnownTypes__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.MapWellKnownTypes), descriptor.MessageTypes[3],
-              new string[] { "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField", }, new string[] { });
+          new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.Proto.Any.Descriptor, global::Google.Protobuf.WellKnownTypes.Proto.Api.Descriptor, global::Google.Protobuf.WellKnownTypes.Proto.Duration.Descriptor, global::Google.Protobuf.WellKnownTypes.Proto.Empty.Descriptor, global::Google.Protobuf.WellKnownTypes.Proto.FieldMask.Descriptor, global::Google.Protobuf.WellKnownTypes.Proto.SourceContext.Descriptor, global::Google.Protobuf.WellKnownTypes.Proto.Struct.Descriptor, global::Google.Protobuf.WellKnownTypes.Proto.Timestamp.Descriptor, global::Google.Protobuf.WellKnownTypes.Proto.Type.Descriptor, global::Google.Protobuf.WellKnownTypes.Wrappers.Descriptor, },
+          new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestWellKnownTypes), new[]{ "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.RepeatedWellKnownTypes), new[]{ "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.OneofWellKnownTypes), new[]{ "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField" }, new[]{ "OneofField" }, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.MapWellKnownTypes), new[]{ "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField" }, null, null, new pbr::GeneratedCodeInfo[] { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, })
+          }));
     }
     #endregion
 
@@ -198,14 +175,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<TestWellKnownTypes> _parser = new pb::MessageParser<TestWellKnownTypes>(() => new TestWellKnownTypes());
     public static pb::MessageParser<TestWellKnownTypes> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "any_field", "api_field", "bool_field", "bytes_field", "double_field", "duration_field", "empty_field", "field_mask_field", "float_field", "int32_field", "int64_field", "source_context_field", "string_field", "struct_field", "timestamp_field", "type_field", "uint32_field", "uint64_field" };
-    private static readonly uint[] _fieldTags = new uint[] { 10, 18, 130, 146, 82, 26, 34, 42, 90, 114, 98, 50, 138, 58, 66, 74, 122, 106 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestWellKnownTypes.Descriptor.MessageTypes[0]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestWellKnownTypes.internal__static_protobuf_unittest_TestWellKnownTypes__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -884,14 +859,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<RepeatedWellKnownTypes> _parser = new pb::MessageParser<RepeatedWellKnownTypes>(() => new RepeatedWellKnownTypes());
     public static pb::MessageParser<RepeatedWellKnownTypes> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "any_field", "api_field", "bool_field", "bytes_field", "double_field", "duration_field", "empty_field", "field_mask_field", "float_field", "int32_field", "int64_field", "source_context_field", "string_field", "struct_field", "timestamp_field", "type_field", "uint32_field", "uint64_field" };
-    private static readonly uint[] _fieldTags = new uint[] { 10, 18, 130, 146, 82, 26, 34, 42, 90, 114, 98, 50, 138, 58, 66, 74, 122, 106 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestWellKnownTypes.Descriptor.MessageTypes[1]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestWellKnownTypes.internal__static_protobuf_unittest_RepeatedWellKnownTypes__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -1318,14 +1291,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<OneofWellKnownTypes> _parser = new pb::MessageParser<OneofWellKnownTypes>(() => new OneofWellKnownTypes());
     public static pb::MessageParser<OneofWellKnownTypes> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "any_field", "api_field", "bool_field", "bytes_field", "double_field", "duration_field", "empty_field", "field_mask_field", "float_field", "int32_field", "int64_field", "source_context_field", "string_field", "struct_field", "timestamp_field", "type_field", "uint32_field", "uint64_field" };
-    private static readonly uint[] _fieldTags = new uint[] { 10, 18, 130, 146, 82, 26, 34, 42, 90, 114, 98, 50, 138, 58, 66, 74, 122, 106 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestWellKnownTypes.Descriptor.MessageTypes[2]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestWellKnownTypes.internal__static_protobuf_unittest_OneofWellKnownTypes__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -2017,14 +1988,12 @@ namespace Google.Protobuf.TestProtos {
     private static readonly pb::MessageParser<MapWellKnownTypes> _parser = new pb::MessageParser<MapWellKnownTypes>(() => new MapWellKnownTypes());
     public static pb::MessageParser<MapWellKnownTypes> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "any_field", "api_field", "bool_field", "bytes_field", "double_field", "duration_field", "empty_field", "field_mask_field", "float_field", "int32_field", "int64_field", "source_context_field", "string_field", "struct_field", "timestamp_field", "type_field", "uint32_field", "uint64_field" };
-    private static readonly uint[] _fieldTags = new uint[] { 10, 18, 130, 146, 82, 26, 34, 42, 90, 114, 98, 50, 138, 58, 66, 74, 122, 106 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestWellKnownTypes.Descriptor.MessageTypes[3]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.TestProtos.UnittestWellKnownTypes.internal__static_protobuf_unittest_MapWellKnownTypes__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;

+ 3 - 3
csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs

@@ -192,7 +192,7 @@ namespace Google.Protobuf.WellKnownTypes
                 Uint32Field = 3,
                 Uint64Field = 4
             };
-            var fields = ((IReflectedMessage) message).Fields;
+            var fields = TestWellKnownTypes.Descriptor.FieldAccessorsByFieldNumber;
 
             Assert.AreEqual("x", fields[TestWellKnownTypes.StringFieldFieldNumber].GetValue(message));
             Assert.AreEqual(ByteString.CopyFrom(1, 2, 3), fields[TestWellKnownTypes.BytesFieldFieldNumber].GetValue(message));
@@ -216,7 +216,7 @@ namespace Google.Protobuf.WellKnownTypes
         {
             // Just a single example... note that we can't have a null value here
             var message = new RepeatedWellKnownTypes { Int32Field = { 1, 2 } };
-            var fields = ((IReflectedMessage) message).Fields;
+            var fields = RepeatedWellKnownTypes.Descriptor.FieldAccessorsByFieldNumber;
             var list = (IList) fields[RepeatedWellKnownTypes.Int32FieldFieldNumber].GetValue(message);
             CollectionAssert.AreEqual(new[] { 1, 2 }, list);
         }
@@ -226,7 +226,7 @@ namespace Google.Protobuf.WellKnownTypes
         {
             // Just a single example... note that we can't have a null value here
             var message = new MapWellKnownTypes { Int32Field = { { 1, 2 }, { 3, null } } };
-            var fields = ((IReflectedMessage) message).Fields;
+            var fields = MapWellKnownTypes.Descriptor.FieldAccessorsByFieldNumber;
             var dictionary = (IDictionary) fields[MapWellKnownTypes.Int32FieldFieldNumber].GetValue(message);
             Assert.AreEqual(2, dictionary[1]);
             Assert.IsNull(dictionary[3]);

+ 3 - 0
csharp/src/Google.Protobuf/Collections/MapField.cs

@@ -30,6 +30,7 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #endregion
 
+using Google.Protobuf.Reflection;
 using System;
 using System.Collections;
 using System.Collections.Generic;
@@ -559,6 +560,8 @@ namespace Google.Protobuf.Collections
                 {
                     return codec.keyCodec.CalculateSizeWithTag(Key) + codec.valueCodec.CalculateSizeWithTag(Value);
                 }
+
+                MessageDescriptor IMessage.Descriptor { get { return null; } }
             }
         }
     }

+ 1 - 1
csharp/src/Google.Protobuf/Google.Protobuf.csproj

@@ -78,10 +78,10 @@
     <Compile Include="Reflection\EnumDescriptor.cs" />
     <Compile Include="Reflection\EnumValueDescriptor.cs" />
     <Compile Include="Reflection\FieldAccessorBase.cs" />
-    <Compile Include="Reflection\FieldAccessorTable.cs" />
     <Compile Include="Reflection\FieldDescriptor.cs" />
     <Compile Include="Reflection\FieldType.cs" />
     <Compile Include="Reflection\FileDescriptor.cs" />
+    <Compile Include="Reflection\GeneratedCodeInfo.cs" />
     <Compile Include="Reflection\IDescriptor.cs" />
     <Compile Include="Reflection\IFieldAccessor.cs" />
     <Compile Include="Reflection\MapFieldAccessor.cs" />

+ 8 - 10
csharp/src/Google.Protobuf/IMessage.cs

@@ -39,15 +39,6 @@ namespace Google.Protobuf
     // TODO(jonskeet): Do we want a "weak" (non-generic) version of IReflectedMessage?
     // TODO(jonskeet): Split these interfaces into separate files when we're happy with them.
 
-    /// <summary>
-    /// Reflection support for accessing field values.
-    /// </summary>
-    public interface IReflectedMessage : IMessage
-    {
-        FieldAccessorTable Fields { get; }
-        // TODO(jonskeet): Descriptor? Or a single property which has "all you need for reflection"?
-    }
-
     /// <summary>
     /// Interface for a Protocol Buffers message, supporting
     /// basic operations required for serialization.
@@ -73,6 +64,13 @@ namespace Google.Protobuf
         /// <returns>The number of bytes required to write this message
         /// to a coded output stream.</returns>
         int CalculateSize();
+
+        /// <summary>
+        /// Descriptor for this message. All instances are expected to return the same descriptor,
+        /// and for generated types this will be an explicitly-implemented member, returning the
+        /// same value as the static property declared on the type.
+        /// </summary>
+        MessageDescriptor Descriptor { get; }
     }
 
     /// <summary>
@@ -81,7 +79,7 @@ namespace Google.Protobuf
     /// the implementation class.
     /// </summary>
     /// <typeparam name="T">The message type.</typeparam>
-    public interface IMessage<T> : IReflectedMessage, IEquatable<T>, IDeepCloneable<T>, IFreezable where T : IMessage<T>
+    public interface IMessage<T> : IMessage, IEquatable<T>, IDeepCloneable<T>, IFreezable where T : IMessage<T>
     {
         /// <summary>
         /// Merges the given message into this one.

+ 13 - 13
csharp/src/Google.Protobuf/JsonFormatter.cs

@@ -118,7 +118,7 @@ namespace Google.Protobuf
             this.settings = settings;
         }
 
-        public string Format(IReflectedMessage message)
+        public string Format(IMessage message)
         {
             ThrowHelper.ThrowIfNull(message, "message");
             StringBuilder builder = new StringBuilder();
@@ -129,7 +129,7 @@ namespace Google.Protobuf
             return builder.ToString();
         }
 
-        private void WriteMessage(StringBuilder builder, IReflectedMessage message)
+        private void WriteMessage(StringBuilder builder, IMessage message)
         {
             if (message == null)
             {
@@ -137,15 +137,15 @@ namespace Google.Protobuf
                 return;
             }
             builder.Append("{ ");
-            var fields = message.Fields;
+            var fields = message.Descriptor.Fields;
             bool first = true;
             // First non-oneof fields
-            foreach (var accessor in fields.Accessors)
+            foreach (var field in fields)
             {
-                var descriptor = accessor.Descriptor;
+                var accessor = field.Accessor;
                 // Oneofs are written later
                 // TODO: Change to write out fields in order, interleaving oneofs appropriately (as per binary format)
-                if (descriptor.ContainingOneof != null)
+                if (field.ContainingOneof != null)
                 {
                     continue;
                 }
@@ -156,7 +156,7 @@ namespace Google.Protobuf
                     continue;
                 }
                 // Omit awkward (single) values such as unknown enum values
-                if (!descriptor.IsRepeated && !descriptor.IsMap && !CanWriteSingleValue(accessor.Descriptor, value))
+                if (!field.IsRepeated && !field.IsMap && !CanWriteSingleValue(accessor.Descriptor, value))
                 {
                     continue;
                 }
@@ -173,15 +173,15 @@ namespace Google.Protobuf
             }
 
             // Now oneofs
-            foreach (var accessor in fields.Oneofs)
+            foreach (var oneof in message.Descriptor.Oneofs)
             {
+                var accessor = oneof.Accessor;
                 var fieldDescriptor = accessor.GetCaseFieldDescriptor(message);
                 if (fieldDescriptor == null)
                 {
                     continue;
                 }
-                var fieldAccessor = fields[fieldDescriptor.FieldNumber];
-                object value = fieldAccessor.GetValue(message);
+                object value = fieldDescriptor.Accessor.GetValue(message);
                 // Omit awkward (single) values such as unknown enum values
                 if (!fieldDescriptor.IsRepeated && !fieldDescriptor.IsMap && !CanWriteSingleValue(fieldDescriptor, value))
                 {
@@ -194,7 +194,7 @@ namespace Google.Protobuf
                 }
                 WriteString(builder, ToCamelCase(fieldDescriptor.Name));
                 builder.Append(": ");
-                WriteValue(builder, fieldAccessor, value);
+                WriteValue(builder, fieldDescriptor.Accessor, value);
                 first = false;
             }
             builder.Append(first ? "}" : " }");
@@ -385,7 +385,7 @@ namespace Google.Protobuf
                     }
                     else
                     {
-                        WriteMessage(builder, (IReflectedMessage) value);
+                        WriteMessage(builder, (IMessage) value);
                     }
                     break;
                 default:
@@ -406,7 +406,7 @@ namespace Google.Protobuf
                 WriteSingleValue(builder, descriptor.MessageType.FindFieldByNumber(1), value);
                 return;
             }
-            WriteMessage(builder, (IReflectedMessage) value);
+            WriteMessage(builder, (IMessage) value);
         }
 
         private void WriteList(StringBuilder builder, IFieldAccessor accessor, IList list)

+ 67 - 181
csharp/src/Google.Protobuf/Reflection/DescriptorProtoFile.cs

@@ -12,30 +12,6 @@ namespace Google.Protobuf.Reflection {
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
   internal static partial class DescriptorProtoFile {
 
-    #region Static variables
-    internal static pbr::FieldAccessorTable internal__static_google_protobuf_FileDescriptorSet__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_google_protobuf_FileDescriptorProto__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_google_protobuf_DescriptorProto__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_google_protobuf_DescriptorProto_ExtensionRange__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_google_protobuf_DescriptorProto_ReservedRange__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_google_protobuf_FieldDescriptorProto__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_google_protobuf_OneofDescriptorProto__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_google_protobuf_EnumDescriptorProto__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_google_protobuf_EnumValueDescriptorProto__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_google_protobuf_ServiceDescriptorProto__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_google_protobuf_MethodDescriptorProto__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_google_protobuf_FileOptions__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_google_protobuf_MessageOptions__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_google_protobuf_FieldOptions__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_google_protobuf_EnumOptions__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_google_protobuf_EnumValueOptions__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_google_protobuf_ServiceOptions__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_google_protobuf_MethodOptions__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_google_protobuf_UninterpretedOption__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_google_protobuf_UninterpretedOption_NamePart__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_google_protobuf_SourceCodeInfo__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_google_protobuf_SourceCodeInfo_Location__FieldAccessorTable;
-    #endregion
     #region Descriptor
     public static pbr::FileDescriptor Descriptor {
       get { return descriptor; }
@@ -155,76 +131,30 @@ namespace Google.Protobuf.Reflection {
             "YWlsaW5nX2NvbW1lbnRzGAQgASgJEiEKGWxlYWRpbmdfZGV0YWNoZWRfY29t", 
             "bWVudHMYBiADKAlCWAoTY29tLmdvb2dsZS5wcm90b2J1ZkIQRGVzY3JpcHRv", 
             "clByb3Rvc0gBWgpkZXNjcmlwdG9yogIDR1BCqgIaR29vZ2xlLlByb3RvYnVm", 
-          "LlJlZmxlY3Rpb24="));
+            "LlJlZmxlY3Rpb24="));
       descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
-          new pbr::FileDescriptor[] {
-          });
-      internal__static_google_protobuf_FileDescriptorSet__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.Reflection.FileDescriptorSet), descriptor.MessageTypes[0],
-              new string[] { "File", }, new string[] { });
-      internal__static_google_protobuf_FileDescriptorProto__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.Reflection.FileDescriptorProto), descriptor.MessageTypes[1],
-              new string[] { "Name", "Package", "Dependency", "PublicDependency", "WeakDependency", "MessageType", "EnumType", "Service", "Extension", "Options", "SourceCodeInfo", "Syntax", }, new string[] { });
-      internal__static_google_protobuf_DescriptorProto__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.Reflection.DescriptorProto), descriptor.MessageTypes[2],
-              new string[] { "Name", "Field", "Extension", "NestedType", "EnumType", "ExtensionRange", "OneofDecl", "Options", "ReservedRange", "ReservedName", }, new string[] { });
-      internal__static_google_protobuf_DescriptorProto_ExtensionRange__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.Reflection.DescriptorProto.Types.ExtensionRange), descriptor.MessageTypes[2].NestedTypes[0],
-              new string[] { "Start", "End", }, new string[] { });
-      internal__static_google_protobuf_DescriptorProto_ReservedRange__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.Reflection.DescriptorProto.Types.ReservedRange), descriptor.MessageTypes[2].NestedTypes[1],
-              new string[] { "Start", "End", }, new string[] { });
-      internal__static_google_protobuf_FieldDescriptorProto__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.Reflection.FieldDescriptorProto), descriptor.MessageTypes[3],
-              new string[] { "Name", "Number", "Label", "Type", "TypeName", "Extendee", "DefaultValue", "OneofIndex", "Options", }, new string[] { });
-      internal__static_google_protobuf_OneofDescriptorProto__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.Reflection.OneofDescriptorProto), descriptor.MessageTypes[4],
-              new string[] { "Name", }, new string[] { });
-      internal__static_google_protobuf_EnumDescriptorProto__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.Reflection.EnumDescriptorProto), descriptor.MessageTypes[5],
-              new string[] { "Name", "Value", "Options", }, new string[] { });
-      internal__static_google_protobuf_EnumValueDescriptorProto__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.Reflection.EnumValueDescriptorProto), descriptor.MessageTypes[6],
-              new string[] { "Name", "Number", "Options", }, new string[] { });
-      internal__static_google_protobuf_ServiceDescriptorProto__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.Reflection.ServiceDescriptorProto), descriptor.MessageTypes[7],
-              new string[] { "Name", "Method", "Options", }, new string[] { });
-      internal__static_google_protobuf_MethodDescriptorProto__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.Reflection.MethodDescriptorProto), descriptor.MessageTypes[8],
-              new string[] { "Name", "InputType", "OutputType", "Options", "ClientStreaming", "ServerStreaming", }, new string[] { });
-      internal__static_google_protobuf_FileOptions__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.Reflection.FileOptions), descriptor.MessageTypes[9],
-              new string[] { "JavaPackage", "JavaOuterClassname", "JavaMultipleFiles", "JavaGenerateEqualsAndHash", "JavaStringCheckUtf8", "OptimizeFor", "GoPackage", "CcGenericServices", "JavaGenericServices", "PyGenericServices", "Deprecated", "CcEnableArenas", "ObjcClassPrefix", "CsharpNamespace", "UninterpretedOption", }, new string[] { });
-      internal__static_google_protobuf_MessageOptions__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.Reflection.MessageOptions), descriptor.MessageTypes[10],
-              new string[] { "MessageSetWireFormat", "NoStandardDescriptorAccessor", "Deprecated", "MapEntry", "UninterpretedOption", }, new string[] { });
-      internal__static_google_protobuf_FieldOptions__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.Reflection.FieldOptions), descriptor.MessageTypes[11],
-              new string[] { "Ctype", "Packed", "Jstype", "Lazy", "Deprecated", "Weak", "UninterpretedOption", }, new string[] { });
-      internal__static_google_protobuf_EnumOptions__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.Reflection.EnumOptions), descriptor.MessageTypes[12],
-              new string[] { "AllowAlias", "Deprecated", "UninterpretedOption", }, new string[] { });
-      internal__static_google_protobuf_EnumValueOptions__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.Reflection.EnumValueOptions), descriptor.MessageTypes[13],
-              new string[] { "Deprecated", "UninterpretedOption", }, new string[] { });
-      internal__static_google_protobuf_ServiceOptions__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.Reflection.ServiceOptions), descriptor.MessageTypes[14],
-              new string[] { "Deprecated", "UninterpretedOption", }, new string[] { });
-      internal__static_google_protobuf_MethodOptions__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.Reflection.MethodOptions), descriptor.MessageTypes[15],
-              new string[] { "Deprecated", "UninterpretedOption", }, new string[] { });
-      internal__static_google_protobuf_UninterpretedOption__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.Reflection.UninterpretedOption), descriptor.MessageTypes[16],
-              new string[] { "Name", "IdentifierValue", "PositiveIntValue", "NegativeIntValue", "DoubleValue", "StringValue", "AggregateValue", }, new string[] { });
-      internal__static_google_protobuf_UninterpretedOption_NamePart__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.Reflection.UninterpretedOption.Types.NamePart), descriptor.MessageTypes[16].NestedTypes[0],
-              new string[] { "NamePart_", "IsExtension", }, new string[] { });
-      internal__static_google_protobuf_SourceCodeInfo__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.Reflection.SourceCodeInfo), descriptor.MessageTypes[17],
-              new string[] { "Location", }, new string[] { });
-      internal__static_google_protobuf_SourceCodeInfo_Location__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.Reflection.SourceCodeInfo.Types.Location), descriptor.MessageTypes[17].NestedTypes[0],
-              new string[] { "Path", "Span", "LeadingComments", "TrailingComments", "LeadingDetachedComments", }, new string[] { });
+          new pbr::FileDescriptor[] { },
+          new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.FileDescriptorSet), new[]{ "File" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.FileDescriptorProto), new[]{ "Name", "Package", "Dependency", "PublicDependency", "WeakDependency", "MessageType", "EnumType", "Service", "Extension", "Options", "SourceCodeInfo", "Syntax" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto), new[]{ "Name", "Field", "Extension", "NestedType", "EnumType", "ExtensionRange", "OneofDecl", "Options", "ReservedRange", "ReservedName" }, null, null, new pbr::GeneratedCodeInfo[] { new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto.Types.ExtensionRange), new[]{ "Start", "End" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto.Types.ReservedRange), new[]{ "Start", "End" }, null, null, null)}),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.FieldDescriptorProto), new[]{ "Name", "Number", "Label", "Type", "TypeName", "Extendee", "DefaultValue", "OneofIndex", "Options" }, null, new[]{ typeof(global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type), typeof(global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label) }, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.OneofDescriptorProto), new[]{ "Name" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.EnumDescriptorProto), new[]{ "Name", "Value", "Options" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.EnumValueDescriptorProto), new[]{ "Name", "Number", "Options" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.ServiceDescriptorProto), new[]{ "Name", "Method", "Options" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.MethodDescriptorProto), new[]{ "Name", "InputType", "OutputType", "Options", "ClientStreaming", "ServerStreaming" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.FileOptions), new[]{ "JavaPackage", "JavaOuterClassname", "JavaMultipleFiles", "JavaGenerateEqualsAndHash", "JavaStringCheckUtf8", "OptimizeFor", "GoPackage", "CcGenericServices", "JavaGenericServices", "PyGenericServices", "Deprecated", "CcEnableArenas", "ObjcClassPrefix", "CsharpNamespace", "UninterpretedOption" }, null, new[]{ typeof(global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode) }, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.MessageOptions), new[]{ "MessageSetWireFormat", "NoStandardDescriptorAccessor", "Deprecated", "MapEntry", "UninterpretedOption" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.FieldOptions), new[]{ "Ctype", "Packed", "Jstype", "Lazy", "Deprecated", "Weak", "UninterpretedOption" }, null, new[]{ typeof(global::Google.Protobuf.Reflection.FieldOptions.Types.CType), typeof(global::Google.Protobuf.Reflection.FieldOptions.Types.JSType) }, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.EnumOptions), new[]{ "AllowAlias", "Deprecated", "UninterpretedOption" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.EnumValueOptions), new[]{ "Deprecated", "UninterpretedOption" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.ServiceOptions), new[]{ "Deprecated", "UninterpretedOption" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.MethodOptions), new[]{ "Deprecated", "UninterpretedOption" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.UninterpretedOption), new[]{ "Name", "IdentifierValue", "PositiveIntValue", "NegativeIntValue", "DoubleValue", "StringValue", "AggregateValue" }, null, null, new pbr::GeneratedCodeInfo[] { new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.UninterpretedOption.Types.NamePart), new[]{ "NamePart_", "IsExtension" }, null, null, null)}),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.SourceCodeInfo), new[]{ "Location" }, null, null, new pbr::GeneratedCodeInfo[] { new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.SourceCodeInfo.Types.Location), new[]{ "Path", "Span", "LeadingComments", "TrailingComments", "LeadingDetachedComments" }, null, null, null)})
+          }));
     }
     #endregion
 
@@ -235,14 +165,12 @@ namespace Google.Protobuf.Reflection {
     private static readonly pb::MessageParser<FileDescriptorSet> _parser = new pb::MessageParser<FileDescriptorSet>(() => new FileDescriptorSet());
     public static pb::MessageParser<FileDescriptorSet> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "file" };
-    private static readonly uint[] _fieldTags = new uint[] { 10 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.Descriptor.MessageTypes[0]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.internal__static_google_protobuf_FileDescriptorSet__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -346,14 +274,12 @@ namespace Google.Protobuf.Reflection {
     private static readonly pb::MessageParser<FileDescriptorProto> _parser = new pb::MessageParser<FileDescriptorProto>(() => new FileDescriptorProto());
     public static pb::MessageParser<FileDescriptorProto> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "dependency", "enum_type", "extension", "message_type", "name", "options", "package", "public_dependency", "service", "source_code_info", "syntax", "weak_dependency" };
-    private static readonly uint[] _fieldTags = new uint[] { 26, 42, 58, 34, 10, 66, 18, 80, 50, 74, 98, 88 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.Descriptor.MessageTypes[1]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.internal__static_google_protobuf_FileDescriptorProto__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -722,14 +648,12 @@ namespace Google.Protobuf.Reflection {
     private static readonly pb::MessageParser<DescriptorProto> _parser = new pb::MessageParser<DescriptorProto>(() => new DescriptorProto());
     public static pb::MessageParser<DescriptorProto> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "enum_type", "extension", "extension_range", "field", "name", "nested_type", "oneof_decl", "options", "reserved_name", "reserved_range" };
-    private static readonly uint[] _fieldTags = new uint[] { 34, 50, 42, 18, 10, 26, 66, 58, 82, 74 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.Descriptor.MessageTypes[2]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.internal__static_google_protobuf_DescriptorProto__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -1028,14 +952,12 @@ namespace Google.Protobuf.Reflection {
         private static readonly pb::MessageParser<ExtensionRange> _parser = new pb::MessageParser<ExtensionRange>(() => new ExtensionRange());
         public static pb::MessageParser<ExtensionRange> Parser { get { return _parser; } }
 
-        private static readonly string[] _fieldNames = new string[] { "end", "start" };
-        private static readonly uint[] _fieldTags = new uint[] { 16, 8 };
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.Reflection.DescriptorProto.Descriptor.NestedTypes[0]; }
         }
 
-        pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-          get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.internal__static_google_protobuf_DescriptorProto_ExtensionRange__FieldAccessorTable; }
+        pbr::MessageDescriptor pb::IMessage.Descriptor {
+          get { return Descriptor; }
         }
 
         private bool _frozen = false;
@@ -1174,14 +1096,12 @@ namespace Google.Protobuf.Reflection {
         private static readonly pb::MessageParser<ReservedRange> _parser = new pb::MessageParser<ReservedRange>(() => new ReservedRange());
         public static pb::MessageParser<ReservedRange> Parser { get { return _parser; } }
 
-        private static readonly string[] _fieldNames = new string[] { "end", "start" };
-        private static readonly uint[] _fieldTags = new uint[] { 16, 8 };
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.Reflection.DescriptorProto.Descriptor.NestedTypes[1]; }
         }
 
-        pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-          get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.internal__static_google_protobuf_DescriptorProto_ReservedRange__FieldAccessorTable; }
+        pbr::MessageDescriptor pb::IMessage.Descriptor {
+          get { return Descriptor; }
         }
 
         private bool _frozen = false;
@@ -1325,14 +1245,12 @@ namespace Google.Protobuf.Reflection {
     private static readonly pb::MessageParser<FieldDescriptorProto> _parser = new pb::MessageParser<FieldDescriptorProto>(() => new FieldDescriptorProto());
     public static pb::MessageParser<FieldDescriptorProto> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "default_value", "extendee", "label", "name", "number", "oneof_index", "options", "type", "type_name" };
-    private static readonly uint[] _fieldTags = new uint[] { 58, 18, 32, 10, 24, 72, 66, 40, 50 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.Descriptor.MessageTypes[3]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.internal__static_google_protobuf_FieldDescriptorProto__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -1700,14 +1618,12 @@ namespace Google.Protobuf.Reflection {
     private static readonly pb::MessageParser<OneofDescriptorProto> _parser = new pb::MessageParser<OneofDescriptorProto>(() => new OneofDescriptorProto());
     public static pb::MessageParser<OneofDescriptorProto> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "name" };
-    private static readonly uint[] _fieldTags = new uint[] { 10 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.Descriptor.MessageTypes[4]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.internal__static_google_protobuf_OneofDescriptorProto__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -1819,14 +1735,12 @@ namespace Google.Protobuf.Reflection {
     private static readonly pb::MessageParser<EnumDescriptorProto> _parser = new pb::MessageParser<EnumDescriptorProto>(() => new EnumDescriptorProto());
     public static pb::MessageParser<EnumDescriptorProto> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "name", "options", "value" };
-    private static readonly uint[] _fieldTags = new uint[] { 10, 26, 18 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.Descriptor.MessageTypes[5]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.internal__static_google_protobuf_EnumDescriptorProto__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -1991,14 +1905,12 @@ namespace Google.Protobuf.Reflection {
     private static readonly pb::MessageParser<EnumValueDescriptorProto> _parser = new pb::MessageParser<EnumValueDescriptorProto>(() => new EnumValueDescriptorProto());
     public static pb::MessageParser<EnumValueDescriptorProto> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "name", "number", "options" };
-    private static readonly uint[] _fieldTags = new uint[] { 10, 16, 26 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.Descriptor.MessageTypes[6]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.internal__static_google_protobuf_EnumValueDescriptorProto__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -2171,14 +2083,12 @@ namespace Google.Protobuf.Reflection {
     private static readonly pb::MessageParser<ServiceDescriptorProto> _parser = new pb::MessageParser<ServiceDescriptorProto>(() => new ServiceDescriptorProto());
     public static pb::MessageParser<ServiceDescriptorProto> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "method", "name", "options" };
-    private static readonly uint[] _fieldTags = new uint[] { 18, 10, 26 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.Descriptor.MessageTypes[7]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.internal__static_google_protobuf_ServiceDescriptorProto__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -2343,14 +2253,12 @@ namespace Google.Protobuf.Reflection {
     private static readonly pb::MessageParser<MethodDescriptorProto> _parser = new pb::MessageParser<MethodDescriptorProto>(() => new MethodDescriptorProto());
     public static pb::MessageParser<MethodDescriptorProto> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "client_streaming", "input_type", "name", "options", "output_type", "server_streaming" };
-    private static readonly uint[] _fieldTags = new uint[] { 40, 18, 10, 34, 26, 48 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.Descriptor.MessageTypes[8]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.internal__static_google_protobuf_MethodDescriptorProto__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -2604,14 +2512,12 @@ namespace Google.Protobuf.Reflection {
     private static readonly pb::MessageParser<FileOptions> _parser = new pb::MessageParser<FileOptions>(() => new FileOptions());
     public static pb::MessageParser<FileOptions> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "cc_enable_arenas", "cc_generic_services", "csharp_namespace", "deprecated", "go_package", "java_generate_equals_and_hash", "java_generic_services", "java_multiple_files", "java_outer_classname", "java_package", "java_string_check_utf8", "objc_class_prefix", "optimize_for", "py_generic_services", "uninterpreted_option" };
-    private static readonly uint[] _fieldTags = new uint[] { 248, 128, 298, 184, 90, 160, 136, 80, 66, 10, 216, 290, 72, 144, 7994 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.Descriptor.MessageTypes[9]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.internal__static_google_protobuf_FileOptions__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -3105,14 +3011,12 @@ namespace Google.Protobuf.Reflection {
     private static readonly pb::MessageParser<MessageOptions> _parser = new pb::MessageParser<MessageOptions>(() => new MessageOptions());
     public static pb::MessageParser<MessageOptions> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "deprecated", "map_entry", "message_set_wire_format", "no_standard_descriptor_accessor", "uninterpreted_option" };
-    private static readonly uint[] _fieldTags = new uint[] { 24, 56, 8, 16, 7994 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.Descriptor.MessageTypes[10]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.internal__static_google_protobuf_MessageOptions__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -3324,14 +3228,12 @@ namespace Google.Protobuf.Reflection {
     private static readonly pb::MessageParser<FieldOptions> _parser = new pb::MessageParser<FieldOptions>(() => new FieldOptions());
     public static pb::MessageParser<FieldOptions> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "ctype", "deprecated", "jstype", "lazy", "packed", "uninterpreted_option", "weak" };
-    private static readonly uint[] _fieldTags = new uint[] { 8, 24, 48, 40, 16, 7994, 80 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.Descriptor.MessageTypes[11]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.internal__static_google_protobuf_FieldOptions__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -3615,14 +3517,12 @@ namespace Google.Protobuf.Reflection {
     private static readonly pb::MessageParser<EnumOptions> _parser = new pb::MessageParser<EnumOptions>(() => new EnumOptions());
     public static pb::MessageParser<EnumOptions> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "allow_alias", "deprecated", "uninterpreted_option" };
-    private static readonly uint[] _fieldTags = new uint[] { 16, 24, 7994 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.Descriptor.MessageTypes[12]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.internal__static_google_protobuf_EnumOptions__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -3780,14 +3680,12 @@ namespace Google.Protobuf.Reflection {
     private static readonly pb::MessageParser<EnumValueOptions> _parser = new pb::MessageParser<EnumValueOptions>(() => new EnumValueOptions());
     public static pb::MessageParser<EnumValueOptions> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "deprecated", "uninterpreted_option" };
-    private static readonly uint[] _fieldTags = new uint[] { 8, 7994 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.Descriptor.MessageTypes[13]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.internal__static_google_protobuf_EnumValueOptions__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -3918,14 +3816,12 @@ namespace Google.Protobuf.Reflection {
     private static readonly pb::MessageParser<ServiceOptions> _parser = new pb::MessageParser<ServiceOptions>(() => new ServiceOptions());
     public static pb::MessageParser<ServiceOptions> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "deprecated", "uninterpreted_option" };
-    private static readonly uint[] _fieldTags = new uint[] { 264, 7994 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.Descriptor.MessageTypes[14]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.internal__static_google_protobuf_ServiceOptions__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -4056,14 +3952,12 @@ namespace Google.Protobuf.Reflection {
     private static readonly pb::MessageParser<MethodOptions> _parser = new pb::MessageParser<MethodOptions>(() => new MethodOptions());
     public static pb::MessageParser<MethodOptions> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "deprecated", "uninterpreted_option" };
-    private static readonly uint[] _fieldTags = new uint[] { 264, 7994 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.Descriptor.MessageTypes[15]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.internal__static_google_protobuf_MethodOptions__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -4194,14 +4088,12 @@ namespace Google.Protobuf.Reflection {
     private static readonly pb::MessageParser<UninterpretedOption> _parser = new pb::MessageParser<UninterpretedOption>(() => new UninterpretedOption());
     public static pb::MessageParser<UninterpretedOption> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "aggregate_value", "double_value", "identifier_value", "name", "negative_int_value", "positive_int_value", "string_value" };
-    private static readonly uint[] _fieldTags = new uint[] { 66, 49, 26, 18, 40, 32, 58 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.Descriptor.MessageTypes[16]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.internal__static_google_protobuf_UninterpretedOption__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -4468,14 +4360,12 @@ namespace Google.Protobuf.Reflection {
         private static readonly pb::MessageParser<NamePart> _parser = new pb::MessageParser<NamePart>(() => new NamePart());
         public static pb::MessageParser<NamePart> Parser { get { return _parser; } }
 
-        private static readonly string[] _fieldNames = new string[] { "is_extension", "name_part" };
-        private static readonly uint[] _fieldTags = new uint[] { 16, 10 };
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.Reflection.UninterpretedOption.Descriptor.NestedTypes[0]; }
         }
 
-        pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-          get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.internal__static_google_protobuf_UninterpretedOption_NamePart__FieldAccessorTable; }
+        pbr::MessageDescriptor pb::IMessage.Descriptor {
+          get { return Descriptor; }
         }
 
         private bool _frozen = false;
@@ -4619,14 +4509,12 @@ namespace Google.Protobuf.Reflection {
     private static readonly pb::MessageParser<SourceCodeInfo> _parser = new pb::MessageParser<SourceCodeInfo>(() => new SourceCodeInfo());
     public static pb::MessageParser<SourceCodeInfo> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "location" };
-    private static readonly uint[] _fieldTags = new uint[] { 10 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.Descriptor.MessageTypes[17]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.internal__static_google_protobuf_SourceCodeInfo__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -4731,14 +4619,12 @@ namespace Google.Protobuf.Reflection {
         private static readonly pb::MessageParser<Location> _parser = new pb::MessageParser<Location>(() => new Location());
         public static pb::MessageParser<Location> Parser { get { return _parser; } }
 
-        private static readonly string[] _fieldNames = new string[] { "leading_comments", "leading_detached_comments", "path", "span", "trailing_comments" };
-        private static readonly uint[] _fieldTags = new uint[] { 26, 50, 10, 18, 34 };
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.Reflection.SourceCodeInfo.Descriptor.NestedTypes[0]; }
         }
 
-        pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-          get { return global::Google.Protobuf.Reflection.DescriptorProtoFile.internal__static_google_protobuf_SourceCodeInfo_Location__FieldAccessorTable; }
+        pbr::MessageDescriptor pb::IMessage.Descriptor {
+          get { return Descriptor; }
         }
 
         private bool _frozen = false;

+ 2 - 3
csharp/src/Google.Protobuf/Reflection/DescriptorUtil.cs

@@ -50,9 +50,8 @@ namespace Google.Protobuf.Reflection
         /// Converts the given array into a read-only list, applying the specified conversion to
         /// each input element.
         /// </summary>
-        internal static IList<TOutput> ConvertAndMakeReadOnly<TInput, TOutput>(IList<TInput> input,
-                                                                               IndexedConverter<TInput, TOutput>
-                                                                                   converter)
+        internal static IList<TOutput> ConvertAndMakeReadOnly<TInput, TOutput>
+            (IList<TInput> input, IndexedConverter<TInput, TOutput> converter)
         {
             TOutput[] array = new TOutput[input.Count];
             for (int i = 0; i < array.Length; i++)

+ 9 - 1
csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs

@@ -30,6 +30,7 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #endregion
 
+using System;
 using System.Collections.Generic;
 
 namespace Google.Protobuf.Reflection
@@ -42,11 +43,13 @@ namespace Google.Protobuf.Reflection
         private readonly EnumDescriptorProto proto;
         private readonly MessageDescriptor containingType;
         private readonly IList<EnumValueDescriptor> values;
+        private readonly Type generatedType;
 
-        internal EnumDescriptor(EnumDescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int index)
+        internal EnumDescriptor(EnumDescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int index, Type generatedType)
             : base(file, file.ComputeFullName(parent, proto.Name), index)
         {
             this.proto = proto;
+            this.generatedType = generatedType;
             containingType = parent;
 
             if (proto.Value.Count == 0)
@@ -69,6 +72,11 @@ namespace Google.Protobuf.Reflection
         /// </summary>
         public override string Name { get { return proto.Name; } }
 
+        /// <summary>
+        /// The generated type for this enum, or <c>null</c> if the descriptor does not represent a generated type.
+        /// </summary>
+        public Type GeneratedType { get { return generatedType; } }
+
         /// <value>
         /// If this is a nested type, get the outer descriptor, otherwise null.
         /// </value>

+ 1 - 6
csharp/src/Google.Protobuf/Reflection/FieldAccessorBase.cs

@@ -43,13 +43,8 @@ namespace Google.Protobuf.Reflection
         private readonly Func<object, object> getValueDelegate;
         private readonly FieldDescriptor descriptor;
 
-        internal FieldAccessorBase(Type type, string propertyName, FieldDescriptor descriptor)
+        internal FieldAccessorBase(PropertyInfo property, FieldDescriptor descriptor)
         {
-            PropertyInfo property = type.GetProperty(propertyName);
-            if (property == null || !property.CanRead)
-            {
-                throw new ArgumentException("Not all required properties/methods available");
-            }
             this.descriptor = descriptor;
             getValueDelegate = ReflectionUtil.CreateFuncObjectObject(property.GetGetMethod());
         }

+ 0 - 97
csharp/src/Google.Protobuf/Reflection/FieldAccessorTable.cs

@@ -1,97 +0,0 @@
-#region Copyright notice and license
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// 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 System.Collections.ObjectModel;
-
-namespace Google.Protobuf.Reflection
-{
-    /// <summary>
-    /// Provides access to fields in generated messages via reflection.
-    /// </summary>
-    public sealed class FieldAccessorTable
-    {
-        private readonly ReadOnlyCollection<IFieldAccessor> accessors;
-        private readonly ReadOnlyCollection<OneofAccessor> oneofs;
-        private readonly MessageDescriptor descriptor;
-
-        /// <summary>
-        /// Constructs a FieldAccessorTable for a particular message class.
-        /// Only one FieldAccessorTable should be constructed per class.
-        /// </summary>
-        /// <param name="type">The CLR type for the message.</param>
-        /// <param name="descriptor">The type's descriptor</param>
-        /// <param name="propertyNames">The Pascal-case names of all the field-based properties in the message.</param>
-        public FieldAccessorTable(Type type, MessageDescriptor descriptor, string[] propertyNames, string[] oneofPropertyNames)
-        {
-            this.descriptor = descriptor;
-            var accessorsArray = new IFieldAccessor[descriptor.Fields.Count];
-            for (int i = 0; i < accessorsArray.Length; i++)
-            {
-                var field = descriptor.Fields[i];
-                var name = propertyNames[i];
-                accessorsArray[i] =
-                    field.IsMap ? new MapFieldAccessor(type, name, field)
-                    : field.IsRepeated ? new RepeatedFieldAccessor(type, name, field)
-                    : (IFieldAccessor) new SingleFieldAccessor(type, name, field);
-            }
-            accessors = new ReadOnlyCollection<IFieldAccessor>(accessorsArray);
-            var oneofsArray = new OneofAccessor[descriptor.Oneofs.Count];
-            for (int i = 0; i < oneofsArray.Length; i++)
-            {
-                var oneof = descriptor.Oneofs[i];
-                oneofsArray[i] = new OneofAccessor(type, oneofPropertyNames[i], oneof);
-            }
-            oneofs = new ReadOnlyCollection<OneofAccessor>(oneofsArray);
-        }
-
-        // TODO: Validate the name here... should possibly make this type a more "general reflection access" type,
-        // bearing in mind the oneof parts to come as well.
-        /// <summary>
-        /// Returns all of the field accessors for the message type.
-        /// </summary>
-        public ReadOnlyCollection<IFieldAccessor> Accessors { get { return accessors; } }
-
-        public ReadOnlyCollection<OneofAccessor> Oneofs { get { return oneofs; } }
-
-        // TODO: Review this, as it's easy to get confused between FieldNumber and Index.
-        // Currently only used to get an accessor related to a oneof... maybe just make that simpler?
-        public IFieldAccessor this[int fieldNumber]
-        {
-            get
-            {
-                FieldDescriptor field = descriptor.FindFieldByNumber(fieldNumber);
-                return accessors[field.Index];
-            }
-        }
-    }
-}

+ 29 - 1
csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs

@@ -31,6 +31,7 @@
 #endregion
 
 using System;
+using System.Linq;
 
 namespace Google.Protobuf.Reflection
 {
@@ -45,9 +46,11 @@ namespace Google.Protobuf.Reflection
         private readonly MessageDescriptor containingType;
         private readonly OneofDescriptor containingOneof;
         private FieldType fieldType;
+        private readonly string propertyName; // Annoyingly, needed in Crosslink.
+        private IFieldAccessor accessor;
 
         internal FieldDescriptor(FieldDescriptorProto proto, FileDescriptor file,
-                                 MessageDescriptor parent, int index)
+                                 MessageDescriptor parent, int index, string propertyName)
             : base(file, file.ComputeFullName(parent, proto.Name), index)
         {
             this.proto = proto;
@@ -74,6 +77,12 @@ namespace Google.Protobuf.Reflection
             }
 
             file.DescriptorPool.AddSymbol(this);
+            // We can't create the accessor until we've cross-linked, unfortunately, as we
+            // may not know whether the type of the field is a map or not. Remember the property name
+            // for later.
+            // We could trust the generated code and check whether the type of the property is
+            // a MapField, but that feels a tad nasty.
+            this.propertyName = propertyName;
         }
 
         /// <summary>
@@ -82,6 +91,8 @@ namespace Google.Protobuf.Reflection
         public override string Name { get { return proto.Name; } }
 
         internal FieldDescriptorProto Proto { get { return proto; } }
+
+        public IFieldAccessor Accessor { get { return accessor; } }
         
         /// <summary>
         /// Maps a field type as included in the .proto file to a FieldType.
@@ -287,6 +298,23 @@ namespace Google.Protobuf.Reflection
             {
                 throw new DescriptorValidationException(this, "MessageSet format is not supported.");
             }
+            accessor = CreateAccessor(propertyName);
+        }
+
+        private IFieldAccessor CreateAccessor(string propertyName)
+        {
+            if (containingType.GeneratedType == null || propertyName == null)
+            {
+                return null;
+            }
+            var property = containingType.GeneratedType.GetProperty(propertyName);
+            if (property == null)
+            {
+                throw new DescriptorValidationException(this, "Property " + propertyName + " not found in " + containingType.GeneratedType);
+            }
+            return IsMap ? new MapFieldAccessor(property, this)
+                : IsRepeated ? new RepeatedFieldAccessor(property, this)
+                : (IFieldAccessor) new SingleFieldAccessor(property, this);
         }
     }
 }

+ 18 - 8
csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs

@@ -62,7 +62,7 @@ namespace Google.Protobuf.Reflection
             get { return proto.Syntax == "proto3" ? ProtoSyntax.Proto3 : ProtoSyntax.Proto2; }
         }
 
-        private FileDescriptor(FileDescriptorProto proto, FileDescriptor[] dependencies, DescriptorPool pool, bool allowUnknownDependencies)
+        private FileDescriptor(FileDescriptorProto proto, FileDescriptor[] dependencies, DescriptorPool pool, bool allowUnknownDependencies, GeneratedCodeInfo generatedCodeInfo)
         {
             this.pool = pool;
             this.proto = proto;
@@ -74,11 +74,11 @@ namespace Google.Protobuf.Reflection
 
             messageTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.MessageType,
                                                                  (message, index) =>
-                                                                 new MessageDescriptor(message, this, null, index));
+                                                                 new MessageDescriptor(message, this, null, index, generatedCodeInfo == null ? null : generatedCodeInfo.NestedTypes[index]));
 
             enumTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.EnumType,
                                                               (enumType, index) =>
-                                                              new EnumDescriptor(enumType, this, null, index));
+                                                              new EnumDescriptor(enumType, this, null, index, generatedCodeInfo == null ? null : generatedCodeInfo.NestedEnums[index]));
 
             services = DescriptorUtil.ConvertAndMakeReadOnly(proto.Service,
                                                              (service, index) =>
@@ -253,7 +253,7 @@ namespace Google.Protobuf.Reflection
             }
             return null;
         }
-        
+
         /// <summary>
         /// Builds a FileDescriptor from its protocol buffer representation.
         /// </summary>
@@ -262,10 +262,11 @@ namespace Google.Protobuf.Reflection
         /// file's dependencies, in the exact order listed in the .proto file. May be null,
         /// in which case it is treated as an empty array.</param>
         /// <param name="allowUnknownDependencies">Whether unknown dependencies are ignored (true) or cause an exception to be thrown (false).</param>
+        /// <param name="generatedCodeInfo">Reflection information, if any. May be null, specifically for non-generated code.</param>
         /// <exception cref="DescriptorValidationException">If <paramref name="proto"/> is not
         /// a valid descriptor. This can occur for a number of reasons, such as a field
         /// having an undefined type or because two messages were defined with the same name.</exception>
-        private static FileDescriptor BuildFrom(FileDescriptorProto proto, FileDescriptor[] dependencies, bool allowUnknownDependencies)
+        private static FileDescriptor BuildFrom(FileDescriptorProto proto, FileDescriptor[] dependencies, bool allowUnknownDependencies, GeneratedCodeInfo generatedCodeInfo)
         {
             // Building descriptors involves two steps: translating and linking.
             // In the translation step (implemented by FileDescriptor's
@@ -282,7 +283,7 @@ namespace Google.Protobuf.Reflection
             }
 
             DescriptorPool pool = new DescriptorPool(dependencies);
-            FileDescriptor result = new FileDescriptor(proto, dependencies, pool, allowUnknownDependencies);
+            FileDescriptor result = new FileDescriptor(proto, dependencies, pool, allowUnknownDependencies, generatedCodeInfo);
 
             // TODO(jonskeet): Reinstate these checks, or get rid of them entirely. They aren't in the Java code,
             // and fail for the CustomOptions test right now. (We get "descriptor.proto" vs "google/protobuf/descriptor.proto".)
@@ -319,8 +320,17 @@ namespace Google.Protobuf.Reflection
             }
         }
 
+        /// <summary>
+        /// Creates an instance for generated code.
+        /// </summary>
+        /// <remarks>
+        /// The <paramref name="generatedCodeInfo"/> parameter should be null for descriptors which don't correspond to
+        /// generated types. Otherwise, it should be a <see cref="GeneratedCodeInfo"/> with nested types and nested
+        /// enums corresponding to the types and enums contained within the file descriptor.
+        /// </remarks>
         public static FileDescriptor InternalBuildGeneratedFileFrom(byte[] descriptorData,
-                                                                    FileDescriptor[] dependencies)
+                                                                    FileDescriptor[] dependencies,
+                                                                    GeneratedCodeInfo generatedCodeInfo)
         {
             FileDescriptorProto proto;
             try
@@ -336,7 +346,7 @@ namespace Google.Protobuf.Reflection
             {
                 // When building descriptors for generated code, we allow unknown
                 // dependencies by default.
-                return BuildFrom(proto, dependencies, true);
+                return BuildFrom(proto, dependencies, true, generatedCodeInfo);
             }
             catch (DescriptorValidationException e)
             {

+ 66 - 0
csharp/src/Google.Protobuf/Reflection/GeneratedCodeInfo.cs

@@ -0,0 +1,66 @@
+using System;
+
+namespace Google.Protobuf.Reflection
+{
+    /// <summary>
+    /// Extra information provided by generated code when initializing a message or file descriptor.
+    /// These are constructed as required, and are not long-lived. Hand-written code should
+    /// never need to use this type.
+    /// </summary>
+    public sealed class GeneratedCodeInfo
+    {
+        private static readonly string[] EmptyNames = new string[0];
+        private static readonly GeneratedCodeInfo[] EmptyCodeInfo = new GeneratedCodeInfo[0];
+
+        /// <summary>
+        /// Irrelevant for file descriptors; the CLR type for the message for message descriptors.
+        /// </summary>
+        public Type ClrType { get; private set; }
+
+        /// <summary>
+        /// Irrelevant for file descriptors; the CLR property names (in message descriptor field order)
+        /// for fields in the message for message descriptors.
+        /// </summary>
+        public string[] PropertyNames { get; private set; }
+
+        /// <summary>
+        /// Irrelevant for file descriptors; the CLR property "base" names (in message descriptor oneof order)
+        /// for oneofs in the message for message descriptors. It is expected that for a oneof name of "Foo",
+        /// there will be a "FooCase" property and a "ClearFoo" method.
+        /// </summary>
+        public string[] OneofNames { get; private set; }
+
+        /// <summary>
+        /// The reflection information for types within this file/message descriptor. Elements may be null
+        /// if there is no corresponding generated type, e.g. for map entry types.
+        /// </summary>
+        public GeneratedCodeInfo[] NestedTypes { get; private set; }
+
+        /// <summary>
+        /// The CLR types for enums within this file/message descriptor.
+        /// </summary>
+        public Type[] NestedEnums { get; private set; }
+
+        /// <summary>
+        /// Creates a GeneratedCodeInfo for a message descriptor, with nested types, nested enums, the CLR type, property names and oneof names.
+        /// Each array parameter may be null, to indicate a lack of values.
+        /// The parameter order is designed to make it feasible to format the generated code readably.
+        /// </summary>
+        public GeneratedCodeInfo(Type clrType, string[] propertyNames, string[] oneofNames, Type[] nestedEnums, GeneratedCodeInfo[] nestedTypes)
+        {
+            NestedTypes = nestedTypes ?? EmptyCodeInfo;
+            NestedEnums = nestedEnums ?? ReflectionUtil.EmptyTypes;
+            ClrType = clrType;
+            PropertyNames = propertyNames ?? EmptyNames;
+            OneofNames = oneofNames ?? EmptyNames;
+        }
+
+        /// <summary>
+        /// Creates a GeneratedCodeInfo for a file descriptor, with only types and enums.
+        /// </summary>
+        public GeneratedCodeInfo(Type[] nestedEnums, GeneratedCodeInfo[] nestedTypes)
+            : this(null, null, null, nestedEnums, nestedTypes)
+        {
+        }
+    }
+}

+ 2 - 1
csharp/src/Google.Protobuf/Reflection/MapFieldAccessor.cs

@@ -32,6 +32,7 @@
 
 using System;
 using System.Collections;
+using System.Reflection;
 
 namespace Google.Protobuf.Reflection
 {
@@ -40,7 +41,7 @@ namespace Google.Protobuf.Reflection
     /// </summary>
     internal sealed class MapFieldAccessor : FieldAccessorBase
     {
-        internal MapFieldAccessor(Type type, string propertyName, FieldDescriptor descriptor) : base(type, propertyName, descriptor)
+        internal MapFieldAccessor(PropertyInfo property, FieldDescriptor descriptor) : base(property, descriptor)
         {
         }
 

+ 50 - 18
csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs

@@ -30,8 +30,10 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #endregion
 
+using Google.Protobuf.Collections;
 using System;
 using System.Collections.Generic;
+using System.Linq;
 
 namespace Google.Protobuf.Reflection
 {
@@ -60,31 +62,47 @@ namespace Google.Protobuf.Reflection
         private readonly IList<EnumDescriptor> enumTypes;
         private readonly IList<FieldDescriptor> fields;
         private readonly IList<OneofDescriptor> oneofs;
+        // CLR representation of the type described by this descriptor, if any.
+        private readonly Type generatedType;
+        private IDictionary<int, IFieldAccessor> fieldAccessorsByFieldNumber;
         
-        internal MessageDescriptor(DescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int typeIndex)
+        internal MessageDescriptor(DescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int typeIndex, GeneratedCodeInfo generatedCodeInfo)
             : base(file, file.ComputeFullName(parent, proto.Name), typeIndex)
         {
             this.proto = proto;
-            containingType = parent;
-
-            oneofs = DescriptorUtil.ConvertAndMakeReadOnly(proto.OneofDecl,
-                                                               (oneof, index) =>
-                                                               new OneofDescriptor(oneof, file, this, index));
+            generatedType = generatedCodeInfo == null ? null : generatedCodeInfo.ClrType;
 
-            nestedTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.NestedType,
-                                                                (type, index) =>
-                                                                new MessageDescriptor(type, file, this, index));
-
-            enumTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.EnumType,
-                                                              (type, index) =>
-                                                              new EnumDescriptor(type, file, this, index));
+            containingType = parent;
 
-            // TODO(jonskeet): Sort fields first?
-            fields = DescriptorUtil.ConvertAndMakeReadOnly(proto.Field,
-                                                           (field, index) =>
-                                                           new FieldDescriptor(field, file, this, index));
+            oneofs = DescriptorUtil.ConvertAndMakeReadOnly(
+                proto.OneofDecl,
+                (oneof, index) =>
+                new OneofDescriptor(oneof, file, this, index, generatedCodeInfo == null ? null : generatedCodeInfo.OneofNames[index]));
+
+            nestedTypes = DescriptorUtil.ConvertAndMakeReadOnly(
+                proto.NestedType,
+                (type, index) =>
+                new MessageDescriptor(type, file, this, index, generatedCodeInfo == null ? null : generatedCodeInfo.NestedTypes[index]));
+
+            enumTypes = DescriptorUtil.ConvertAndMakeReadOnly(
+                proto.EnumType,
+                (type, index) =>
+                new EnumDescriptor(type, file, this, index, generatedCodeInfo == null ? null : generatedCodeInfo.NestedEnums[index]));
+
+            fields = DescriptorUtil.ConvertAndMakeReadOnly(
+                proto.Field,
+                (field, index) =>
+                new FieldDescriptor(field, file, this, index, generatedCodeInfo == null ? null : generatedCodeInfo.PropertyNames[index]));
             file.DescriptorPool.AddSymbol(this);
         }
+                
+        /// <summary>
+        /// Returns the total number of nested types and enums, recursively.
+        /// </summary>
+        private int CountTotalGeneratedTypes()
+        {
+            return nestedTypes.Sum(nested => nested.CountTotalGeneratedTypes()) + enumTypes.Count;
+        }
 
         /// <summary>
         /// The brief name of the descriptor's target.
@@ -93,6 +111,11 @@ namespace Google.Protobuf.Reflection
 
         internal DescriptorProto Proto { get { return proto; } }
 
+        /// <summary>
+        /// The generated type for this message, or <c>null</c> if the descriptor does not represent a generated type.
+        /// </summary>
+        public Type GeneratedType { get { return generatedType; } }
+
         /// <summary>
         /// Returns whether this message is one of the "well known types" which may have runtime/protoc support.
         /// </summary>
@@ -141,6 +164,13 @@ namespace Google.Protobuf.Reflection
             get { return oneofs; }
         }
 
+        /// <summary>
+        /// Returns a map from field number to accessor.
+        /// TODO: Revisit this. It's mostly in place to make the transition from FieldAccessorTable
+        /// to descriptor-based reflection simple in terms of tests. Work out what we really want.
+        /// </summary>
+        public IDictionary<int, IFieldAccessor> FieldAccessorsByFieldNumber { get { return fieldAccessorsByFieldNumber; } }
+
         /// <summary>
         /// Finds a field by field name.
         /// </summary>
@@ -192,6 +222,8 @@ namespace Google.Protobuf.Reflection
             {
                 oneof.CrossLink();
             }
-        }        
+
+            fieldAccessorsByFieldNumber = new ReadOnlyDictionary<int, IFieldAccessor>(fields.ToDictionary(field => field.FieldNumber, field => field.Accessor));
+        }
     }
 }

+ 4 - 6
csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs

@@ -44,18 +44,16 @@ namespace Google.Protobuf.Reflection
         private readonly Action<object> clearDelegate;
         private OneofDescriptor descriptor;
 
-        internal OneofAccessor(Type type, string propertyName, OneofDescriptor descriptor) 
+        internal OneofAccessor(PropertyInfo caseProperty, MethodInfo clearMethod, OneofDescriptor descriptor) 
         {
-            PropertyInfo property = type.GetProperty(propertyName + "Case");
-            if (property == null || !property.CanRead)
+            if (!caseProperty.CanRead)
             {
-                throw new ArgumentException("Not all required properties/methods available");
+                throw new ArgumentException("Cannot read from property");
             }
             this.descriptor = descriptor;
-            caseDelegate = ReflectionUtil.CreateFuncObjectT<int>(property.GetGetMethod());
+            caseDelegate = ReflectionUtil.CreateFuncObjectT<int>(caseProperty.GetGetMethod());
 
             this.descriptor = descriptor;
-            MethodInfo clearMethod = type.GetMethod("Clear" + propertyName);
             clearDelegate = ReflectionUtil.CreateActionObject(clearMethod);
         }
 

+ 26 - 1
csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs

@@ -32,6 +32,7 @@
 
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
+using System.Linq;
 
 namespace Google.Protobuf.Reflection
 {
@@ -40,14 +41,16 @@ namespace Google.Protobuf.Reflection
         private readonly OneofDescriptorProto proto;
         private MessageDescriptor containingType;
         private IList<FieldDescriptor> fields;
+        private readonly OneofAccessor accessor;
 
-        internal OneofDescriptor(OneofDescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int index)
+        internal OneofDescriptor(OneofDescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int index, string clrName)
             : base(file, file.ComputeFullName(parent, proto.Name), index)
         {
             this.proto = proto;
             containingType = parent;
 
             file.DescriptorPool.AddSymbol(this);
+            accessor = CreateAccessor(clrName);
         }
 
         /// <summary>
@@ -62,6 +65,8 @@ namespace Google.Protobuf.Reflection
 
         public IList<FieldDescriptor> Fields { get { return fields; } }
 
+        public OneofAccessor Accessor { get { return accessor; } }
+
         internal void CrossLink()
         {
             List<FieldDescriptor> fieldCollection = new List<FieldDescriptor>();
@@ -74,5 +79,25 @@ namespace Google.Protobuf.Reflection
             }
             fields = new ReadOnlyCollection<FieldDescriptor>(fieldCollection);
         }
+
+        private OneofAccessor CreateAccessor(string clrName)
+        {
+            if (containingType.GeneratedType == null || clrName == null)
+            {
+                return null;
+            }
+            var caseProperty = containingType.GeneratedType.GetProperty(clrName + "Case");
+            if (caseProperty == null)
+            {
+                throw new DescriptorValidationException(this, "Property " + clrName + "Case not found in " + containingType.GeneratedType);
+            }
+            var clearMethod = containingType.GeneratedType.GetMethod("Clear" + clrName, ReflectionUtil.EmptyTypes);
+            if (clearMethod == null)
+            {
+                throw new DescriptorValidationException(this, "Method Clear" + clrName + " not found in " + containingType.GeneratedType);
+            }
+
+            return new OneofAccessor(caseProperty, clearMethod, this);
+        }
     }
 }

+ 2 - 1
csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs

@@ -31,6 +31,7 @@
 #endregion
 
 using System;
+using System.Collections.Generic;
 using System.Linq.Expressions;
 using System.Reflection;
 
@@ -101,6 +102,6 @@ namespace Google.Protobuf.Reflection
             Expression castTarget = Expression.Convert(targetParameter, method.DeclaringType);
             Expression call = Expression.Call(castTarget, method);
             return Expression.Lambda<Action<object>>(call, targetParameter).Compile();
-        }
+        }        
     }
 }

+ 2 - 1
csharp/src/Google.Protobuf/Reflection/RepeatedFieldAccessor.cs

@@ -32,6 +32,7 @@
 
 using System;
 using System.Collections;
+using System.Reflection;
 
 namespace Google.Protobuf.Reflection
 {
@@ -40,7 +41,7 @@ namespace Google.Protobuf.Reflection
     /// </summary>
     internal sealed class RepeatedFieldAccessor : FieldAccessorBase
     {
-        internal RepeatedFieldAccessor(Type type, string propertyName, FieldDescriptor descriptor) : base(type, propertyName, descriptor)
+        internal RepeatedFieldAccessor(PropertyInfo property, FieldDescriptor descriptor) : base(property, descriptor)
         {
         }
 

+ 1 - 4
csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs

@@ -48,11 +48,8 @@ namespace Google.Protobuf.Reflection
         private readonly Action<object, object> setValueDelegate;
         private readonly Action<object> clearDelegate;
 
-        internal SingleFieldAccessor(Type type, string propertyName, FieldDescriptor descriptor) : base(type, propertyName, descriptor)
+        internal SingleFieldAccessor(PropertyInfo property, FieldDescriptor descriptor) : base(property, descriptor)
         {
-            PropertyInfo property = type.GetProperty(propertyName);
-            // We know there *is* such a property, or the base class constructor would have thrown. We should be able to write
-            // to it though.
             if (!property.CanWrite)
             {
                 throw new ArgumentException("Not all required properties/methods available");

+ 7 - 13
csharp/src/Google.Protobuf/WellKnownTypes/Any.cs

@@ -14,9 +14,6 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
     public static partial class Any {
 
-      #region Static variables
-      internal static pbr::FieldAccessorTable internal__static_google_protobuf_Any__FieldAccessorTable;
-      #endregion
       #region Descriptor
       public static pbr::FileDescriptor Descriptor {
         get { return descriptor; }
@@ -29,13 +26,12 @@ namespace Google.Protobuf.WellKnownTypes {
               "Chlnb29nbGUvcHJvdG9idWYvYW55LnByb3RvEg9nb29nbGUucHJvdG9idWYi", 
               "JgoDQW55EhAKCHR5cGVfdXJsGAEgASgJEg0KBXZhbHVlGAIgASgMQksKE2Nv", 
               "bS5nb29nbGUucHJvdG9idWZCCEFueVByb3RvUAGgAQGiAgNHUEKqAh5Hb29n", 
-            "bGUuUHJvdG9idWYuV2VsbEtub3duVHlwZXNiBnByb3RvMw=="));
+              "bGUuUHJvdG9idWYuV2VsbEtub3duVHlwZXNiBnByb3RvMw=="));
         descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
-            new pbr::FileDescriptor[] {
-            });
-        internal__static_google_protobuf_Any__FieldAccessorTable = 
-            new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.WellKnownTypes.Any), descriptor.MessageTypes[0],
-                new string[] { "TypeUrl", "Value", }, new string[] { });
+            new pbr::FileDescriptor[] { },
+            new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
+              new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Any), new[]{ "TypeUrl", "Value" }, null, null, null)
+            }));
       }
       #endregion
 
@@ -47,14 +43,12 @@ namespace Google.Protobuf.WellKnownTypes {
     private static readonly pb::MessageParser<Any> _parser = new pb::MessageParser<Any>(() => new Any());
     public static pb::MessageParser<Any> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "type_url", "value" };
-    private static readonly uint[] _fieldTags = new uint[] { 10, 18 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.Proto.Any.Descriptor.MessageTypes[0]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.WellKnownTypes.Proto.Any.internal__static_google_protobuf_Any__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;

+ 10 - 23
csharp/src/Google.Protobuf/WellKnownTypes/Api.cs

@@ -14,10 +14,6 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
     public static partial class Api {
 
-      #region Static variables
-      internal static pbr::FieldAccessorTable internal__static_google_protobuf_Api__FieldAccessorTable;
-      internal static pbr::FieldAccessorTable internal__static_google_protobuf_Method__FieldAccessorTable;
-      #endregion
       #region Descriptor
       public static pbr::FileDescriptor Descriptor {
         get { return descriptor; }
@@ -39,18 +35,13 @@ namespace Google.Protobuf.WellKnownTypes {
               "ZV9zdHJlYW1pbmcYBSABKAgSKAoHb3B0aW9ucxgGIAMoCzIXLmdvb2dsZS5w", 
               "cm90b2J1Zi5PcHRpb25CSAoTY29tLmdvb2dsZS5wcm90b2J1ZkIIQXBpUHJv", 
               "dG9QAaICA0dQQqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25vd25UeXBlc2IG", 
-            "cHJvdG8z"));
+              "cHJvdG8z"));
         descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
-            new pbr::FileDescriptor[] {
-            global::Google.Protobuf.WellKnownTypes.Proto.SourceContext.Descriptor, 
-            global::Google.Protobuf.WellKnownTypes.Proto.Type.Descriptor, 
-            });
-        internal__static_google_protobuf_Api__FieldAccessorTable = 
-            new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.WellKnownTypes.Api), descriptor.MessageTypes[0],
-                new string[] { "Name", "Methods", "Options", "Version", "SourceContext", }, new string[] { });
-        internal__static_google_protobuf_Method__FieldAccessorTable = 
-            new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.WellKnownTypes.Method), descriptor.MessageTypes[1],
-                new string[] { "Name", "RequestTypeUrl", "RequestStreaming", "ResponseTypeUrl", "ResponseStreaming", "Options", }, new string[] { });
+            new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.Proto.SourceContext.Descriptor, global::Google.Protobuf.WellKnownTypes.Proto.Type.Descriptor, },
+            new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
+              new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Api), new[]{ "Name", "Methods", "Options", "Version", "SourceContext" }, null, null, null),
+              new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Method), new[]{ "Name", "RequestTypeUrl", "RequestStreaming", "ResponseTypeUrl", "ResponseStreaming", "Options" }, null, null, null)
+            }));
       }
       #endregion
 
@@ -62,14 +53,12 @@ namespace Google.Protobuf.WellKnownTypes {
     private static readonly pb::MessageParser<Api> _parser = new pb::MessageParser<Api>(() => new Api());
     public static pb::MessageParser<Api> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "methods", "name", "options", "source_context", "version" };
-    private static readonly uint[] _fieldTags = new uint[] { 18, 10, 26, 42, 34 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.Proto.Api.Descriptor.MessageTypes[0]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.WellKnownTypes.Proto.Api.internal__static_google_protobuf_Api__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -280,14 +269,12 @@ namespace Google.Protobuf.WellKnownTypes {
     private static readonly pb::MessageParser<Method> _parser = new pb::MessageParser<Method>(() => new Method());
     public static pb::MessageParser<Method> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "name", "options", "request_streaming", "request_type_url", "response_streaming", "response_type_url" };
-    private static readonly uint[] _fieldTags = new uint[] { 10, 50, 24, 18, 40, 34 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.Proto.Api.Descriptor.MessageTypes[1]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.WellKnownTypes.Proto.Api.internal__static_google_protobuf_Method__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;

+ 7 - 13
csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs

@@ -14,9 +14,6 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
     public static partial class Duration {
 
-      #region Static variables
-      internal static pbr::FieldAccessorTable internal__static_google_protobuf_Duration__FieldAccessorTable;
-      #endregion
       #region Descriptor
       public static pbr::FileDescriptor Descriptor {
         get { return descriptor; }
@@ -30,13 +27,12 @@ namespace Google.Protobuf.WellKnownTypes {
               "b2J1ZiIqCghEdXJhdGlvbhIPCgdzZWNvbmRzGAEgASgDEg0KBW5hbm9zGAIg", 
               "ASgFQlAKE2NvbS5nb29nbGUucHJvdG9idWZCDUR1cmF0aW9uUHJvdG9QAaAB", 
               "AaICA0dQQqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25vd25UeXBlc2IGcHJv", 
-            "dG8z"));
+              "dG8z"));
         descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
-            new pbr::FileDescriptor[] {
-            });
-        internal__static_google_protobuf_Duration__FieldAccessorTable = 
-            new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.WellKnownTypes.Duration), descriptor.MessageTypes[0],
-                new string[] { "Seconds", "Nanos", }, new string[] { });
+            new pbr::FileDescriptor[] { },
+            new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
+              new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Duration), new[]{ "Seconds", "Nanos" }, null, null, null)
+            }));
       }
       #endregion
 
@@ -48,14 +44,12 @@ namespace Google.Protobuf.WellKnownTypes {
     private static readonly pb::MessageParser<Duration> _parser = new pb::MessageParser<Duration>(() => new Duration());
     public static pb::MessageParser<Duration> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "nanos", "seconds" };
-    private static readonly uint[] _fieldTags = new uint[] { 16, 8 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.Proto.Duration.Descriptor.MessageTypes[0]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.WellKnownTypes.Proto.Duration.internal__static_google_protobuf_Duration__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;

+ 7 - 13
csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs

@@ -14,9 +14,6 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
     public static partial class Empty {
 
-      #region Static variables
-      internal static pbr::FieldAccessorTable internal__static_google_protobuf_Empty__FieldAccessorTable;
-      #endregion
       #region Descriptor
       public static pbr::FileDescriptor Descriptor {
         get { return descriptor; }
@@ -29,13 +26,12 @@ namespace Google.Protobuf.WellKnownTypes {
               "Chtnb29nbGUvcHJvdG9idWYvZW1wdHkucHJvdG8SD2dvb2dsZS5wcm90b2J1", 
               "ZiIHCgVFbXB0eUJKChNjb20uZ29vZ2xlLnByb3RvYnVmQgpFbXB0eVByb3Rv", 
               "UAGiAgNHUEKqAh5Hb29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlwZXNiBnBy", 
-            "b3RvMw=="));
+              "b3RvMw=="));
         descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
-            new pbr::FileDescriptor[] {
-            });
-        internal__static_google_protobuf_Empty__FieldAccessorTable = 
-            new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.WellKnownTypes.Empty), descriptor.MessageTypes[0],
-                new string[] { }, new string[] { });
+            new pbr::FileDescriptor[] { },
+            new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
+              new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Empty), null, null, null, null)
+            }));
       }
       #endregion
 
@@ -47,14 +43,12 @@ namespace Google.Protobuf.WellKnownTypes {
     private static readonly pb::MessageParser<Empty> _parser = new pb::MessageParser<Empty>(() => new Empty());
     public static pb::MessageParser<Empty> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] {  };
-    private static readonly uint[] _fieldTags = new uint[] {  };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.Proto.Empty.Descriptor.MessageTypes[0]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.WellKnownTypes.Proto.Empty.internal__static_google_protobuf_Empty__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;

+ 7 - 13
csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs

@@ -14,9 +14,6 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
     public static partial class FieldMask {
 
-      #region Static variables
-      internal static pbr::FieldAccessorTable internal__static_google_protobuf_FieldMask__FieldAccessorTable;
-      #endregion
       #region Descriptor
       public static pbr::FileDescriptor Descriptor {
         get { return descriptor; }
@@ -29,13 +26,12 @@ namespace Google.Protobuf.WellKnownTypes {
               "CiBnb29nbGUvcHJvdG9idWYvZmllbGRfbWFzay5wcm90bxIPZ29vZ2xlLnBy", 
               "b3RvYnVmIhoKCUZpZWxkTWFzaxINCgVwYXRocxgBIAMoCUJOChNjb20uZ29v", 
               "Z2xlLnByb3RvYnVmQg5GaWVsZE1hc2tQcm90b1ABogIDR1BCqgIeR29vZ2xl", 
-            "LlByb3RvYnVmLldlbGxLbm93blR5cGVzYgZwcm90bzM="));
+              "LlByb3RvYnVmLldlbGxLbm93blR5cGVzYgZwcm90bzM="));
         descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
-            new pbr::FileDescriptor[] {
-            });
-        internal__static_google_protobuf_FieldMask__FieldAccessorTable = 
-            new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.WellKnownTypes.FieldMask), descriptor.MessageTypes[0],
-                new string[] { "Paths", }, new string[] { });
+            new pbr::FileDescriptor[] { },
+            new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
+              new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.FieldMask), new[]{ "Paths" }, null, null, null)
+            }));
       }
       #endregion
 
@@ -47,14 +43,12 @@ namespace Google.Protobuf.WellKnownTypes {
     private static readonly pb::MessageParser<FieldMask> _parser = new pb::MessageParser<FieldMask>(() => new FieldMask());
     public static pb::MessageParser<FieldMask> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "paths" };
-    private static readonly uint[] _fieldTags = new uint[] { 10 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.Proto.FieldMask.Descriptor.MessageTypes[0]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.WellKnownTypes.Proto.FieldMask.internal__static_google_protobuf_FieldMask__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;

+ 7 - 13
csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs

@@ -14,9 +14,6 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
     public static partial class SourceContext {
 
-      #region Static variables
-      internal static pbr::FieldAccessorTable internal__static_google_protobuf_SourceContext__FieldAccessorTable;
-      #endregion
       #region Descriptor
       public static pbr::FileDescriptor Descriptor {
         get { return descriptor; }
@@ -30,13 +27,12 @@ namespace Google.Protobuf.WellKnownTypes {
               "ZS5wcm90b2J1ZiIiCg1Tb3VyY2VDb250ZXh0EhEKCWZpbGVfbmFtZRgBIAEo", 
               "CUJSChNjb20uZ29vZ2xlLnByb3RvYnVmQhJTb3VyY2VDb250ZXh0UHJvdG9Q", 
               "AaICA0dQQqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25vd25UeXBlc2IGcHJv", 
-            "dG8z"));
+              "dG8z"));
         descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
-            new pbr::FileDescriptor[] {
-            });
-        internal__static_google_protobuf_SourceContext__FieldAccessorTable = 
-            new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.WellKnownTypes.SourceContext), descriptor.MessageTypes[0],
-                new string[] { "FileName", }, new string[] { });
+            new pbr::FileDescriptor[] { },
+            new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
+              new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.SourceContext), new[]{ "FileName" }, null, null, null)
+            }));
       }
       #endregion
 
@@ -48,14 +44,12 @@ namespace Google.Protobuf.WellKnownTypes {
     private static readonly pb::MessageParser<SourceContext> _parser = new pb::MessageParser<SourceContext>(() => new SourceContext());
     public static pb::MessageParser<SourceContext> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "file_name" };
-    private static readonly uint[] _fieldTags = new uint[] { 10 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.Proto.SourceContext.Descriptor.MessageTypes[0]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.WellKnownTypes.Proto.SourceContext.internal__static_google_protobuf_SourceContext__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;

+ 13 - 29
csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs

@@ -14,11 +14,6 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
     public static partial class Struct {
 
-      #region Static variables
-      internal static pbr::FieldAccessorTable internal__static_google_protobuf_Struct__FieldAccessorTable;
-      internal static pbr::FieldAccessorTable internal__static_google_protobuf_Value__FieldAccessorTable;
-      internal static pbr::FieldAccessorTable internal__static_google_protobuf_ListValue__FieldAccessorTable;
-      #endregion
       #region Descriptor
       public static pbr::FileDescriptor Descriptor {
         get { return descriptor; }
@@ -41,19 +36,14 @@ namespace Google.Protobuf.WellKnownTypes {
               "Lmdvb2dsZS5wcm90b2J1Zi5WYWx1ZSobCglOdWxsVmFsdWUSDgoKTlVMTF9W", 
               "QUxVRRAAQk4KE2NvbS5nb29nbGUucHJvdG9idWZCC1N0cnVjdFByb3RvUAGg", 
               "AQGiAgNHUEKqAh5Hb29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlwZXNiBnBy", 
-            "b3RvMw=="));
+              "b3RvMw=="));
         descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
-            new pbr::FileDescriptor[] {
-            });
-        internal__static_google_protobuf_Struct__FieldAccessorTable = 
-            new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.WellKnownTypes.Struct), descriptor.MessageTypes[0],
-                new string[] { "Fields", }, new string[] { });
-        internal__static_google_protobuf_Value__FieldAccessorTable = 
-            new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.WellKnownTypes.Value), descriptor.MessageTypes[1],
-                new string[] { "NullValue", "NumberValue", "StringValue", "BoolValue", "StructValue", "ListValue", }, new string[] { "Kind", });
-        internal__static_google_protobuf_ListValue__FieldAccessorTable = 
-            new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.WellKnownTypes.ListValue), descriptor.MessageTypes[2],
-                new string[] { "Values", }, new string[] { });
+            new pbr::FileDescriptor[] { },
+            new pbr::GeneratedCodeInfo(new[] {typeof(global::Google.Protobuf.WellKnownTypes.NullValue), }, new pbr::GeneratedCodeInfo[] {
+              new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Struct), new[]{ "Fields" }, null, null, new pbr::GeneratedCodeInfo[] { null, }),
+              new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Value), new[]{ "NullValue", "NumberValue", "StringValue", "BoolValue", "StructValue", "ListValue" }, new[]{ "Kind" }, null, null),
+              new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.ListValue), new[]{ "Values" }, null, null, null)
+            }));
       }
       #endregion
 
@@ -72,14 +62,12 @@ namespace Google.Protobuf.WellKnownTypes {
     private static readonly pb::MessageParser<Struct> _parser = new pb::MessageParser<Struct>(() => new Struct());
     public static pb::MessageParser<Struct> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "fields" };
-    private static readonly uint[] _fieldTags = new uint[] { 10 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.Proto.Struct.Descriptor.MessageTypes[0]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.WellKnownTypes.Proto.Struct.internal__static_google_protobuf_Struct__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -183,14 +171,12 @@ namespace Google.Protobuf.WellKnownTypes {
     private static readonly pb::MessageParser<Value> _parser = new pb::MessageParser<Value>(() => new Value());
     public static pb::MessageParser<Value> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "bool_value", "list_value", "null_value", "number_value", "string_value", "struct_value" };
-    private static readonly uint[] _fieldTags = new uint[] { 32, 50, 8, 17, 26, 42 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.Proto.Struct.Descriptor.MessageTypes[1]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.WellKnownTypes.Proto.Struct.internal__static_google_protobuf_Value__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -488,14 +474,12 @@ namespace Google.Protobuf.WellKnownTypes {
     private static readonly pb::MessageParser<ListValue> _parser = new pb::MessageParser<ListValue>(() => new ListValue());
     public static pb::MessageParser<ListValue> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "values" };
-    private static readonly uint[] _fieldTags = new uint[] { 10 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.Proto.Struct.Descriptor.MessageTypes[2]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.WellKnownTypes.Proto.Struct.internal__static_google_protobuf_ListValue__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;

+ 7 - 13
csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs

@@ -14,9 +14,6 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
     public static partial class Timestamp {
 
-      #region Static variables
-      internal static pbr::FieldAccessorTable internal__static_google_protobuf_Timestamp__FieldAccessorTable;
-      #endregion
       #region Descriptor
       public static pbr::FileDescriptor Descriptor {
         get { return descriptor; }
@@ -30,13 +27,12 @@ namespace Google.Protobuf.WellKnownTypes {
               "dG9idWYiKwoJVGltZXN0YW1wEg8KB3NlY29uZHMYASABKAMSDQoFbmFub3MY", 
               "AiABKAVCUQoTY29tLmdvb2dsZS5wcm90b2J1ZkIOVGltZXN0YW1wUHJvdG9Q", 
               "AaABAaICA0dQQqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25vd25UeXBlc2IG", 
-            "cHJvdG8z"));
+              "cHJvdG8z"));
         descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
-            new pbr::FileDescriptor[] {
-            });
-        internal__static_google_protobuf_Timestamp__FieldAccessorTable = 
-            new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.WellKnownTypes.Timestamp), descriptor.MessageTypes[0],
-                new string[] { "Seconds", "Nanos", }, new string[] { });
+            new pbr::FileDescriptor[] { },
+            new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
+              new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Timestamp), new[]{ "Seconds", "Nanos" }, null, null, null)
+            }));
       }
       #endregion
 
@@ -48,14 +44,12 @@ namespace Google.Protobuf.WellKnownTypes {
     private static readonly pb::MessageParser<Timestamp> _parser = new pb::MessageParser<Timestamp>(() => new Timestamp());
     public static pb::MessageParser<Timestamp> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "nanos", "seconds" };
-    private static readonly uint[] _fieldTags = new uint[] { 16, 8 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.Proto.Timestamp.Descriptor.MessageTypes[0]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.WellKnownTypes.Proto.Timestamp.internal__static_google_protobuf_Timestamp__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;

+ 19 - 47
csharp/src/Google.Protobuf/WellKnownTypes/Type.cs

@@ -14,13 +14,6 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
     public static partial class Type {
 
-      #region Static variables
-      internal static pbr::FieldAccessorTable internal__static_google_protobuf_Type__FieldAccessorTable;
-      internal static pbr::FieldAccessorTable internal__static_google_protobuf_Field__FieldAccessorTable;
-      internal static pbr::FieldAccessorTable internal__static_google_protobuf_Enum__FieldAccessorTable;
-      internal static pbr::FieldAccessorTable internal__static_google_protobuf_EnumValue__FieldAccessorTable;
-      internal static pbr::FieldAccessorTable internal__static_google_protobuf_Option__FieldAccessorTable;
-      #endregion
       #region Descriptor
       public static pbr::FileDescriptor Descriptor {
         get { return descriptor; }
@@ -60,27 +53,16 @@ namespace Google.Protobuf.WellKnownTypes {
               "cHRpb24SDAoEbmFtZRgBIAEoCRIjCgV2YWx1ZRgCIAEoCzIULmdvb2dsZS5w", 
               "cm90b2J1Zi5BbnlCSQoTY29tLmdvb2dsZS5wcm90b2J1ZkIJVHlwZVByb3Rv", 
               "UAGiAgNHUEKqAh5Hb29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlwZXNiBnBy", 
-            "b3RvMw=="));
+              "b3RvMw=="));
         descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
-            new pbr::FileDescriptor[] {
-            global::Google.Protobuf.WellKnownTypes.Proto.Any.Descriptor, 
-            global::Google.Protobuf.WellKnownTypes.Proto.SourceContext.Descriptor, 
-            });
-        internal__static_google_protobuf_Type__FieldAccessorTable = 
-            new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.WellKnownTypes.Type), descriptor.MessageTypes[0],
-                new string[] { "Name", "Fields", "Oneofs", "Options", "SourceContext", }, new string[] { });
-        internal__static_google_protobuf_Field__FieldAccessorTable = 
-            new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.WellKnownTypes.Field), descriptor.MessageTypes[1],
-                new string[] { "Kind", "Cardinality", "Number", "Name", "TypeUrl", "OneofIndex", "Packed", "Options", }, new string[] { });
-        internal__static_google_protobuf_Enum__FieldAccessorTable = 
-            new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.WellKnownTypes.Enum), descriptor.MessageTypes[2],
-                new string[] { "Name", "Enumvalue", "Options", "SourceContext", }, new string[] { });
-        internal__static_google_protobuf_EnumValue__FieldAccessorTable = 
-            new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.WellKnownTypes.EnumValue), descriptor.MessageTypes[3],
-                new string[] { "Name", "Number", "Options", }, new string[] { });
-        internal__static_google_protobuf_Option__FieldAccessorTable = 
-            new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.WellKnownTypes.Option), descriptor.MessageTypes[4],
-                new string[] { "Name", "Value", }, new string[] { });
+            new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.Proto.Any.Descriptor, global::Google.Protobuf.WellKnownTypes.Proto.SourceContext.Descriptor, },
+            new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
+              new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Type), new[]{ "Name", "Fields", "Oneofs", "Options", "SourceContext" }, null, null, null),
+              new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Field), new[]{ "Kind", "Cardinality", "Number", "Name", "TypeUrl", "OneofIndex", "Packed", "Options" }, null, new[]{ typeof(global::Google.Protobuf.WellKnownTypes.Field.Types.Kind), typeof(global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality) }, null),
+              new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Enum), new[]{ "Name", "Enumvalue", "Options", "SourceContext" }, null, null, null),
+              new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.EnumValue), new[]{ "Name", "Number", "Options" }, null, null, null),
+              new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Option), new[]{ "Name", "Value" }, null, null, null)
+            }));
       }
       #endregion
 
@@ -92,14 +74,12 @@ namespace Google.Protobuf.WellKnownTypes {
     private static readonly pb::MessageParser<Type> _parser = new pb::MessageParser<Type>(() => new Type());
     public static pb::MessageParser<Type> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "fields", "name", "oneofs", "options", "source_context" };
-    private static readonly uint[] _fieldTags = new uint[] { 18, 10, 26, 34, 42 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.Proto.Type.Descriptor.MessageTypes[0]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.WellKnownTypes.Proto.Type.internal__static_google_protobuf_Type__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -302,14 +282,12 @@ namespace Google.Protobuf.WellKnownTypes {
     private static readonly pb::MessageParser<Field> _parser = new pb::MessageParser<Field>(() => new Field());
     public static pb::MessageParser<Field> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "cardinality", "kind", "name", "number", "oneof_index", "options", "packed", "type_url" };
-    private static readonly uint[] _fieldTags = new uint[] { 16, 8, 34, 24, 56, 74, 64, 50 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.Proto.Type.Descriptor.MessageTypes[1]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.WellKnownTypes.Proto.Type.internal__static_google_protobuf_Field__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -636,14 +614,12 @@ namespace Google.Protobuf.WellKnownTypes {
     private static readonly pb::MessageParser<Enum> _parser = new pb::MessageParser<Enum>(() => new Enum());
     public static pb::MessageParser<Enum> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "enumvalue", "name", "options", "source_context" };
-    private static readonly uint[] _fieldTags = new uint[] { 18, 10, 26, 34 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.Proto.Type.Descriptor.MessageTypes[2]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.WellKnownTypes.Proto.Type.internal__static_google_protobuf_Enum__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -827,14 +803,12 @@ namespace Google.Protobuf.WellKnownTypes {
     private static readonly pb::MessageParser<EnumValue> _parser = new pb::MessageParser<EnumValue>(() => new EnumValue());
     public static pb::MessageParser<EnumValue> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "name", "number", "options" };
-    private static readonly uint[] _fieldTags = new uint[] { 10, 16, 26 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.Proto.Type.Descriptor.MessageTypes[3]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.WellKnownTypes.Proto.Type.internal__static_google_protobuf_EnumValue__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -992,14 +966,12 @@ namespace Google.Protobuf.WellKnownTypes {
     private static readonly pb::MessageParser<Option> _parser = new pb::MessageParser<Option>(() => new Option());
     public static pb::MessageParser<Option> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "name", "value" };
-    private static readonly uint[] _fieldTags = new uint[] { 10, 18 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.Proto.Type.Descriptor.MessageTypes[4]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.WellKnownTypes.Proto.Type.internal__static_google_protobuf_Option__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;

+ 31 - 77
csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs

@@ -12,17 +12,6 @@ namespace Google.Protobuf.WellKnownTypes {
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
   public static partial class Wrappers {
 
-    #region Static variables
-    internal static pbr::FieldAccessorTable internal__static_google_protobuf_DoubleValue__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_google_protobuf_FloatValue__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_google_protobuf_Int64Value__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_google_protobuf_UInt64Value__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_google_protobuf_Int32Value__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_google_protobuf_UInt32Value__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_google_protobuf_BoolValue__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_google_protobuf_StringValue__FieldAccessorTable;
-    internal static pbr::FieldAccessorTable internal__static_google_protobuf_BytesValue__FieldAccessorTable;
-    #endregion
     #region Descriptor
     public static pbr::FileDescriptor Descriptor {
       get { return descriptor; }
@@ -40,37 +29,20 @@ namespace Google.Protobuf.WellKnownTypes {
             "DSIaCglCb29sVmFsdWUSDQoFdmFsdWUYASABKAgiHAoLU3RyaW5nVmFsdWUS", 
             "DQoFdmFsdWUYASABKAkiGwoKQnl0ZXNWYWx1ZRINCgV2YWx1ZRgBIAEoDEJN", 
             "ChNjb20uZ29vZ2xlLnByb3RvYnVmQg1XcmFwcGVyc1Byb3RvUAGiAgNHUEKq", 
-          "Ah5Hb29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlwZXNiBnByb3RvMw=="));
+            "Ah5Hb29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlwZXNiBnByb3RvMw=="));
       descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
-          new pbr::FileDescriptor[] {
-          });
-      internal__static_google_protobuf_DoubleValue__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.WellKnownTypes.DoubleValue), descriptor.MessageTypes[0],
-              new string[] { "Value", }, new string[] { });
-      internal__static_google_protobuf_FloatValue__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.WellKnownTypes.FloatValue), descriptor.MessageTypes[1],
-              new string[] { "Value", }, new string[] { });
-      internal__static_google_protobuf_Int64Value__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.WellKnownTypes.Int64Value), descriptor.MessageTypes[2],
-              new string[] { "Value", }, new string[] { });
-      internal__static_google_protobuf_UInt64Value__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.WellKnownTypes.UInt64Value), descriptor.MessageTypes[3],
-              new string[] { "Value", }, new string[] { });
-      internal__static_google_protobuf_Int32Value__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.WellKnownTypes.Int32Value), descriptor.MessageTypes[4],
-              new string[] { "Value", }, new string[] { });
-      internal__static_google_protobuf_UInt32Value__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.WellKnownTypes.UInt32Value), descriptor.MessageTypes[5],
-              new string[] { "Value", }, new string[] { });
-      internal__static_google_protobuf_BoolValue__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.WellKnownTypes.BoolValue), descriptor.MessageTypes[6],
-              new string[] { "Value", }, new string[] { });
-      internal__static_google_protobuf_StringValue__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.WellKnownTypes.StringValue), descriptor.MessageTypes[7],
-              new string[] { "Value", }, new string[] { });
-      internal__static_google_protobuf_BytesValue__FieldAccessorTable = 
-          new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.WellKnownTypes.BytesValue), descriptor.MessageTypes[8],
-              new string[] { "Value", }, new string[] { });
+          new pbr::FileDescriptor[] { },
+          new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.DoubleValue), new[]{ "Value" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.FloatValue), new[]{ "Value" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Int64Value), new[]{ "Value" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.UInt64Value), new[]{ "Value" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Int32Value), new[]{ "Value" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.UInt32Value), new[]{ "Value" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.BoolValue), new[]{ "Value" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.StringValue), new[]{ "Value" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.BytesValue), new[]{ "Value" }, null, null, null)
+          }));
     }
     #endregion
 
@@ -81,14 +53,12 @@ namespace Google.Protobuf.WellKnownTypes {
     private static readonly pb::MessageParser<DoubleValue> _parser = new pb::MessageParser<DoubleValue>(() => new DoubleValue());
     public static pb::MessageParser<DoubleValue> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "value" };
-    private static readonly uint[] _fieldTags = new uint[] { 9 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.Wrappers.Descriptor.MessageTypes[0]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.WellKnownTypes.Wrappers.internal__static_google_protobuf_DoubleValue__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -200,14 +170,12 @@ namespace Google.Protobuf.WellKnownTypes {
     private static readonly pb::MessageParser<FloatValue> _parser = new pb::MessageParser<FloatValue>(() => new FloatValue());
     public static pb::MessageParser<FloatValue> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "value" };
-    private static readonly uint[] _fieldTags = new uint[] { 13 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.Wrappers.Descriptor.MessageTypes[1]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.WellKnownTypes.Wrappers.internal__static_google_protobuf_FloatValue__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -319,14 +287,12 @@ namespace Google.Protobuf.WellKnownTypes {
     private static readonly pb::MessageParser<Int64Value> _parser = new pb::MessageParser<Int64Value>(() => new Int64Value());
     public static pb::MessageParser<Int64Value> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "value" };
-    private static readonly uint[] _fieldTags = new uint[] { 8 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.Wrappers.Descriptor.MessageTypes[2]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.WellKnownTypes.Wrappers.internal__static_google_protobuf_Int64Value__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -438,14 +404,12 @@ namespace Google.Protobuf.WellKnownTypes {
     private static readonly pb::MessageParser<UInt64Value> _parser = new pb::MessageParser<UInt64Value>(() => new UInt64Value());
     public static pb::MessageParser<UInt64Value> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "value" };
-    private static readonly uint[] _fieldTags = new uint[] { 8 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.Wrappers.Descriptor.MessageTypes[3]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.WellKnownTypes.Wrappers.internal__static_google_protobuf_UInt64Value__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -557,14 +521,12 @@ namespace Google.Protobuf.WellKnownTypes {
     private static readonly pb::MessageParser<Int32Value> _parser = new pb::MessageParser<Int32Value>(() => new Int32Value());
     public static pb::MessageParser<Int32Value> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "value" };
-    private static readonly uint[] _fieldTags = new uint[] { 8 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.Wrappers.Descriptor.MessageTypes[4]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.WellKnownTypes.Wrappers.internal__static_google_protobuf_Int32Value__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -676,14 +638,12 @@ namespace Google.Protobuf.WellKnownTypes {
     private static readonly pb::MessageParser<UInt32Value> _parser = new pb::MessageParser<UInt32Value>(() => new UInt32Value());
     public static pb::MessageParser<UInt32Value> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "value" };
-    private static readonly uint[] _fieldTags = new uint[] { 8 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.Wrappers.Descriptor.MessageTypes[5]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.WellKnownTypes.Wrappers.internal__static_google_protobuf_UInt32Value__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -795,14 +755,12 @@ namespace Google.Protobuf.WellKnownTypes {
     private static readonly pb::MessageParser<BoolValue> _parser = new pb::MessageParser<BoolValue>(() => new BoolValue());
     public static pb::MessageParser<BoolValue> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "value" };
-    private static readonly uint[] _fieldTags = new uint[] { 8 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.Wrappers.Descriptor.MessageTypes[6]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.WellKnownTypes.Wrappers.internal__static_google_protobuf_BoolValue__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -914,14 +872,12 @@ namespace Google.Protobuf.WellKnownTypes {
     private static readonly pb::MessageParser<StringValue> _parser = new pb::MessageParser<StringValue>(() => new StringValue());
     public static pb::MessageParser<StringValue> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "value" };
-    private static readonly uint[] _fieldTags = new uint[] { 10 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.Wrappers.Descriptor.MessageTypes[7]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.WellKnownTypes.Wrappers.internal__static_google_protobuf_StringValue__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;
@@ -1033,14 +989,12 @@ namespace Google.Protobuf.WellKnownTypes {
     private static readonly pb::MessageParser<BytesValue> _parser = new pb::MessageParser<BytesValue>(() => new BytesValue());
     public static pb::MessageParser<BytesValue> Parser { get { return _parser; } }
 
-    private static readonly string[] _fieldNames = new string[] { "value" };
-    private static readonly uint[] _fieldTags = new uint[] { 10 };
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.Wrappers.Descriptor.MessageTypes[8]; }
     }
 
-    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
-      get { return global::Google.Protobuf.WellKnownTypes.Wrappers.internal__static_google_protobuf_BytesValue__FieldAccessorTable; }
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
     }
 
     private bool _frozen = false;

+ 0 - 5
src/google/protobuf/compiler/csharp/csharp_field_base.cc

@@ -85,7 +85,6 @@ void FieldGeneratorBase::SetCommonFieldVariables(
   }
   (*variables)["capitalized_type_name"] = capitalized_type_name();
   (*variables)["number"] = number();
-  (*variables)["field_ordinal"] = field_ordinal();
   (*variables)["has_property_check"] =
     (*variables)["property_name"] + " != " + (*variables)["default_value"];
   (*variables)["other_has_property_check"] = "other." +
@@ -431,10 +430,6 @@ std::string FieldGeneratorBase::capitalized_type_name() {
   }
 }
 
-std::string FieldGeneratorBase::field_ordinal() {
-  return SimpleItoa(fieldOrdinal_);
-}
-
 }  // namespace csharp
 }  // namespace compiler
 }  // namespace protobuf

+ 0 - 1
src/google/protobuf/compiler/csharp/csharp_field_base.h

@@ -85,7 +85,6 @@ class FieldGeneratorBase : public SourceGeneratorBase {
   std::string default_value(const FieldDescriptor* descriptor);
   std::string number();
   std::string capitalized_type_name();
-  std::string field_ordinal();
 
  private:
   void SetCommonFieldVariables(map<string, string>* variables);

+ 2 - 4
src/google/protobuf/compiler/csharp/csharp_helpers.h

@@ -77,6 +77,8 @@ std::string GetFullUmbrellaClassName(const FileDescriptor* descriptor);
 
 std::string GetQualifiedUmbrellaClassName(const FileDescriptor* descriptor);
 
+std::string GetClassName(const Descriptor* descriptor);
+
 std::string GetClassName(const EnumDescriptor* descriptor);
 
 std::string GetFieldName(const FieldDescriptor* descriptor);
@@ -119,10 +121,6 @@ inline bool IsDescriptorProto(const FileDescriptor* descriptor) {
   return descriptor->name() == "google/protobuf/descriptor_proto_file.proto";
 }
 
-inline bool IsMapEntry(const Descriptor* descriptor) {
-    return descriptor->options().map_entry();
-}
-
 inline bool IsWrapperType(const FieldDescriptor* descriptor) {
   return descriptor->type() == FieldDescriptor::TYPE_MESSAGE &&
       descriptor->message_type()->file()->name() == "google/protobuf/wrappers.proto";

+ 3 - 92
src/google/protobuf/compiler/csharp/csharp_message.cc

@@ -96,88 +96,11 @@ const std::vector<const FieldDescriptor*>& MessageGenerator::fields_by_number()
   return fields_by_number_;
 }
 
-/// Get an identifier that uniquely identifies this type within the file.
-/// This is used to declare static variables related to this type at the
-/// outermost file scope.
-std::string GetUniqueFileScopeIdentifier(const Descriptor* descriptor) {
-  std::string result = descriptor->full_name();
-  std::replace(result.begin(), result.end(), '.', '_');
-  return "static_" + result;
-}
-
-void MessageGenerator::GenerateStaticVariables(io::Printer* printer) {
-  // Because descriptor.proto (Google.Protobuf.DescriptorProtos) is
-  // used in the construction of descriptors, we have a tricky bootstrapping
-  // problem.  To help control static initialization order, we make sure all
-  // descriptors and other static data that depends on them are members of
-  // the proto-descriptor class.  This way, they will be initialized in
-  // a deterministic order.
-
-  std::string identifier = GetUniqueFileScopeIdentifier(descriptor_);
-
-  // The descriptor for this type.
-  printer->Print(
-      "internal static pbr::FieldAccessorTable internal__$identifier$__FieldAccessorTable;\n",
-      "identifier", GetUniqueFileScopeIdentifier(descriptor_),
-      "full_class_name", full_class_name());
-
-  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
-    // Don't generate accessor table fields for maps...
-    if (!IsMapEntryMessage(descriptor_->nested_type(i))) {
-      MessageGenerator messageGenerator(descriptor_->nested_type(i));
-      messageGenerator.GenerateStaticVariables(printer);
-    }
-  }
-}
-
-void MessageGenerator::GenerateStaticVariableInitializers(io::Printer* printer) {
-  map<string, string> vars;
-  vars["identifier"] = GetUniqueFileScopeIdentifier(descriptor_);
-  vars["full_class_name"] = full_class_name();
-
-  // Work out how to get to the message descriptor (which may be multiply nested) from the file
-  // descriptor.
-  string descriptor_chain;
-  const Descriptor* current_descriptor = descriptor_;
-  while (current_descriptor->containing_type()) {
-    descriptor_chain = ".NestedTypes[" + SimpleItoa(current_descriptor->index()) + "]" + descriptor_chain;
-    current_descriptor = current_descriptor->containing_type();
-  }
-  descriptor_chain = "descriptor.MessageTypes[" + SimpleItoa(current_descriptor->index()) + "]" + descriptor_chain;
-  vars["descriptor_chain"] = descriptor_chain;
-
-  printer->Print(
-    vars,
-    "internal__$identifier$__FieldAccessorTable = \n"
-    "    new pbr::FieldAccessorTable(typeof($full_class_name$), $descriptor_chain$,\n");
-  printer->Print("        new string[] { ");
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    printer->Print("\"$property_name$\", ",
-                   "property_name", GetPropertyName(descriptor_->field(i)));
-  }
-  printer->Print("}, new string[] { ");
-  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
-    printer->Print("\"$oneof_name$\", ",
-                   "oneof_name",
-                   UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true));
-  }
-  printer->Print("});\n");
-
-  // Generate static member initializers for all non-map-entry nested types.
-  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
-    if (!IsMapEntryMessage(descriptor_->nested_type(i))) {
-      MessageGenerator messageGenerator(descriptor_->nested_type(i));
-      messageGenerator.GenerateStaticVariableInitializers(printer);
-    }
-  }
-}
-
 void MessageGenerator::Generate(io::Printer* printer) {
   map<string, string> vars;
   vars["class_name"] = class_name();
   vars["access_level"] = class_access_level();
   vars["umbrella_class_name"] = GetFullUmbrellaClassName(descriptor_->file());
-  vars["identifier"] = GetUniqueFileScopeIdentifier(descriptor_);
 
   printer->Print(
     "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n");
@@ -192,19 +115,6 @@ void MessageGenerator::Generate(io::Printer* printer) {
       vars,
       "private static readonly pb::MessageParser<$class_name$> _parser = new pb::MessageParser<$class_name$>(() => new $class_name$());\n"
       "public static pb::MessageParser<$class_name$> Parser { get { return _parser; } }\n\n");
-  printer->Print(
-    "private static readonly string[] _fieldNames = "
-    "new string[] { $slash$$field_names$$slash$ };\n",
-    "field_names", JoinStrings(field_names(), "\", \""),
-      "slash", field_names().size() > 0 ? "\"" : "");
-  std::vector<std::string> tags;
-  for (int i = 0; i < field_names().size(); i++) {
-    uint32 tag = FixedMakeTag(descriptor_->FindFieldByName(field_names()[i]));
-    tags.push_back(SimpleItoa(tag));
-  }
-  printer->Print(
-    "private static readonly uint[] _fieldTags = new uint[] { $tags$ };\n",
-    "tags", JoinStrings(tags, ", "));
 
   // Access the message descriptor via the relevant file descriptor or containing message descriptor.
   if (!descriptor_->containing_type()) {
@@ -221,8 +131,8 @@ void MessageGenerator::Generate(io::Printer* printer) {
     "  get { return $descriptor_accessor$; }\n"
     "}\n"
     "\n"
-    "pbr::FieldAccessorTable pb::IReflectedMessage.Fields {\n"
-    "  get { return $umbrella_class_name$.internal__$identifier$__FieldAccessorTable; }\n"
+    "pbr::MessageDescriptor pb::IMessage.Descriptor {\n"
+    "  get { return Descriptor; }\n"
     "}\n"
     "\n"
     "private bool _frozen = false;\n"
@@ -258,6 +168,7 @@ void MessageGenerator::Generate(io::Printer* printer) {
   for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
     vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false);
     vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true);
+    vars["original_name"] = descriptor_->oneof_decl(i)->name();
     printer->Print(
       vars,
       "private object $name$_;\n"

+ 0 - 2
src/google/protobuf/compiler/csharp/csharp_message.h

@@ -53,8 +53,6 @@ class MessageGenerator : public SourceGeneratorBase {
   void GenerateCloningCode(io::Printer* printer);
   void GenerateFreezingCode(io::Printer* printer);
   void GenerateFrameworkMethods(io::Printer* printer);
-  void GenerateStaticVariables(io::Printer* printer);
-  void GenerateStaticVariableInitializers(io::Printer* printer);
   void Generate(io::Printer* printer);
 
  private:

+ 1 - 1
src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc

@@ -59,7 +59,7 @@ void RepeatedEnumFieldGenerator::GenerateMembers(io::Printer* printer) {
   printer->Print(
     variables_,
     "private static readonly pb::FieldCodec<$type_name$> _repeated_$name$_codec\n"
-    "    = pb::FieldCodec.ForEnum($tag$, x => (int) x, x => ($type_name$) x);");
+    "    = pb::FieldCodec.ForEnum($tag$, x => (int) x, x => ($type_name$) x);\n");
   printer->Print(variables_,
     "private readonly pbc::RepeatedField<$type_name$> $name$_ = new pbc::RepeatedField<$type_name$>();\n");
   AddDeprecatedFlag(printer);

+ 102 - 14
src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc

@@ -36,6 +36,7 @@
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/strutil.h>
 
 
 #include <google/protobuf/compiler/csharp/csharp_enum.h>
@@ -63,12 +64,6 @@ UmbrellaClassGenerator::~UmbrellaClassGenerator() {
 void UmbrellaClassGenerator::Generate(io::Printer* printer) {
   WriteIntroduction(printer);
 
-  printer->Print("#region Static variables\n");
-  for (int i = 0; i < file_->message_type_count(); i++) {
-    MessageGenerator messageGenerator(file_->message_type(i));
-    messageGenerator.GenerateStaticVariables(printer);
-  }
-  printer->Print("#endregion\n");
   WriteDescriptor(printer);
   // Close the class declaration.
   printer->Outdent();
@@ -174,33 +169,126 @@ void UmbrellaClassGenerator::WriteDescriptor(io::Printer* printer) {
     printer->Print("\"$base64$\", \n", "base64", base64.substr(0, 60));
     base64 = base64.substr(60);
   }
-  printer->Outdent();
   printer->Print("\"$base64$\"));\n", "base64", base64);
   printer->Outdent();
   printer->Outdent();
+  printer->Outdent();
 
   // -----------------------------------------------------------------
   // Invoke InternalBuildGeneratedFileFrom() to build the file.
   printer->Print(
       "descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,\n");
-  printer->Print("    new pbr::FileDescriptor[] {\n");
+  printer->Print("    new pbr::FileDescriptor[] { ");
   for (int i = 0; i < file_->dependency_count(); i++) {
     printer->Print(
-      "    $full_umbrella_class_name$.Descriptor, \n",
+      "$full_umbrella_class_name$.Descriptor, ",
       "full_umbrella_class_name",
       GetFullUmbrellaClassName(file_->dependency(i)));
   }
-  printer->Print("    });\n");
-  // Then invoke any other static variable initializers, e.g. field accessors.
-  for (int i = 0; i < file_->message_type_count(); i++) {
-      MessageGenerator messageGenerator(file_->message_type(i));
-      messageGenerator.GenerateStaticVariableInitializers(printer);
+  printer->Print("},\n"
+      "    new pbr::GeneratedCodeInfo(");
+  // Specify all the generated code information, recursively.
+  if (file_->enum_type_count() > 0) {
+      printer->Print("new[] {");
+      for (int i = 0; i < file_->enum_type_count(); i++) {
+          printer->Print("typeof($type_name$), ", "type_name", GetClassName(file_->enum_type(i)));
+      }
+      printer->Print("}, ");
+  }
+  else {
+      printer->Print("null, ");
   }
+  if (file_->message_type_count() > 0) {
+      printer->Print("new pbr::GeneratedCodeInfo[] {\n");
+      printer->Indent();
+      printer->Indent();
+      printer->Indent();
+      for (int i = 0; i < file_->message_type_count(); i++) {
+          WriteGeneratedCodeInfo(file_->message_type(i), printer, i == file_->message_type_count() - 1);
+      }
+      printer->Outdent();
+      printer->Print("\n}));\n");
+      printer->Outdent();
+      printer->Outdent();
+  }
+  else {
+      printer->Print("null));\n");
+  }
+
   printer->Outdent();
   printer->Print("}\n");
   printer->Print("#endregion\n\n");
 }
 
+// Write out the generated code for a particular message. This consists of the CLR type, property names
+// corresponding to fields, names corresponding to oneofs, nested enums, and nested types. Each array part
+// can be specified as null if it would be empty, to make the generated code somewhat simpler to read.
+// We write a line break at the end of each generated code info, so that in the final file we'll see all
+// the types, pre-ordered depth first, one per line. The indentation will be slightly unusual,
+// in that it will look like a single array when it's actually constructing a tree, but it'll be easy to
+// read even with multiple levels of nesting.
+// The "last" parameter indicates whether this message descriptor is the last one being printed in this immediate
+// context. It governs whether or not a trailing comma and newline is written after the constructor, effectively
+// just controlling the formatting in the generated code.
+void UmbrellaClassGenerator::WriteGeneratedCodeInfo(const Descriptor* descriptor, io::Printer* printer, bool last) {
+  if (IsMapEntryMessage(descriptor)) {
+    printer->Print("null, ");
+    return;
+  }
+  // Generated message type
+  printer->Print("new pbr::GeneratedCodeInfo(typeof($type_name$), ", "type_name", GetClassName(descriptor));
+  
+  // Fields
+  if (descriptor->field_count() > 0) {
+      std::vector<std::string> fields;
+      for (int i = 0; i < descriptor->field_count(); i++) {
+          fields.push_back(GetPropertyName(descriptor->field(i)));
+      }
+      printer->Print("new[]{ \"$fields$\" }, ", "fields", JoinStrings(fields, "\", \""));
+  }
+  else {
+      printer->Print("null, ");
+  }
+
+  // Oneofs
+  if (descriptor->oneof_decl_count() > 0) {
+      std::vector<std::string> oneofs;
+      for (int i = 0; i < descriptor->oneof_decl_count(); i++) {
+          oneofs.push_back(UnderscoresToCamelCase(descriptor->oneof_decl(i)->name(), true));
+      }
+      printer->Print("new[]{ \"$oneofs$\" }, ", "oneofs", JoinStrings(oneofs, "\", \""));
+  }
+  else {
+      printer->Print("null, ");
+  }
+
+  // Nested enums
+  if (descriptor->enum_type_count() > 0) {
+      std::vector<std::string> enums;
+      for (int i = 0; i < descriptor->enum_type_count(); i++) {
+          enums.push_back(GetClassName(descriptor->enum_type(i)));
+      }
+      printer->Print("new[]{ typeof($enums$) }, ", "enums", JoinStrings(enums, "), typeof("));
+  }
+  else {
+      printer->Print("null, ");
+  }
+
+  // Nested types
+  if (descriptor->nested_type_count() > 0) {
+      // Need to specify array type explicitly here, as all elements may be null. 
+      printer->Print("new pbr::GeneratedCodeInfo[] { ");
+      for (int i = 0; i < descriptor->nested_type_count(); i++) {
+          WriteGeneratedCodeInfo(descriptor->nested_type(i), printer, i == descriptor->nested_type_count() - 1);
+      }
+      printer->Print("}");
+  }
+  else {
+      printer->Print("null");
+  }
+  printer->Print(last ? ")" : "),\n");
+}
+
 }  // namespace csharp
 }  // namespace compiler
 }  // namespace protobuf

+ 1 - 0
src/google/protobuf/compiler/csharp/csharp_umbrella_class.h

@@ -57,6 +57,7 @@ class UmbrellaClassGenerator : public SourceGeneratorBase {
 
   void WriteIntroduction(io::Printer* printer);
   void WriteDescriptor(io::Printer* printer);
+  void WriteGeneratedCodeInfo(const Descriptor* descriptor, io::Printer* printer, bool last);
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UmbrellaClassGenerator);
 };