Merge pull request #566 from jskeet/csharp-reflection

Improve C# reflection support
diff --git a/csharp/src/AddressBook/Addressbook.cs b/csharp/src/AddressBook/Addressbook.cs
index 4fd4647..5f4a513 100644
--- a/csharp/src/AddressBook/Addressbook.cs
+++ b/csharp/src/AddressBook/Addressbook.cs
@@ -13,12 +13,9 @@
   public static partial class Addressbook {
 
     #region Static variables
-    internal static pbd::MessageDescriptor internal__static_tutorial_Person__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.Examples.AddressBook.Person> internal__static_tutorial_Person__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_tutorial_Person_PhoneNumber__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber> internal__static_tutorial_Person_PhoneNumber__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_tutorial_AddressBook__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.Examples.AddressBook.AddressBook> internal__static_tutorial_AddressBook__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_tutorial_Person__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_tutorial_Person_PhoneNumber__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_tutorial_AddressBook__FieldAccessorTable;
     #endregion
     #region Descriptor
     public static pbd::FileDescriptor Descriptor {
@@ -29,33 +26,27 @@
     static Addressbook() {
       byte[] descriptorData = global::System.Convert.FromBase64String(
           string.Concat(
-            "ChFhZGRyZXNzYm9vay5wcm90bxIIdHV0b3JpYWwi2gEKBlBlcnNvbhIMCgRu", 
-            "YW1lGAEgAigJEgoKAmlkGAIgAigFEg0KBWVtYWlsGAMgASgJEisKBXBob25l", 
-            "GAQgAygLMhwudHV0b3JpYWwuUGVyc29uLlBob25lTnVtYmVyGk0KC1Bob25l", 
-            "TnVtYmVyEg4KBm51bWJlchgBIAIoCRIuCgR0eXBlGAIgASgOMhoudHV0b3Jp", 
-            "YWwuUGVyc29uLlBob25lVHlwZToESE9NRSIrCglQaG9uZVR5cGUSCgoGTU9C", 
-            "SUxFEAASCAoESE9NRRABEggKBFdPUksQAiIvCgtBZGRyZXNzQm9vaxIgCgZw", 
-            "ZXJzb24YASADKAsyEC50dXRvcmlhbC5QZXJzb25CUAoUY29tLmV4YW1wbGUu", 
-            "dHV0b3JpYWxCEUFkZHJlc3NCb29rUHJvdG9zqgIkR29vZ2xlLlByb3RvYnVm", 
-          "LkV4YW1wbGVzLkFkZHJlc3NCb29r"));
-      pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {
-        descriptor = root;
-        internal__static_tutorial_Person__Descriptor = Descriptor.MessageTypes[0];
-        internal__static_tutorial_Person__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.Examples.AddressBook.Person>(internal__static_tutorial_Person__Descriptor,
-                new string[] { "Name", "Id", "Email", "Phone", });
-        internal__static_tutorial_Person_PhoneNumber__Descriptor = internal__static_tutorial_Person__Descriptor.NestedTypes[0];
-        internal__static_tutorial_Person_PhoneNumber__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber>(internal__static_tutorial_Person_PhoneNumber__Descriptor,
-                new string[] { "Number", "Type", });
-        internal__static_tutorial_AddressBook__Descriptor = Descriptor.MessageTypes[1];
-        internal__static_tutorial_AddressBook__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.Examples.AddressBook.AddressBook>(internal__static_tutorial_AddressBook__Descriptor,
-                new string[] { "Person", });
-      };
-      pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
+            "ChFhZGRyZXNzYm9vay5wcm90bxIIdHV0b3JpYWwi1AEKBlBlcnNvbhIMCgRu", 
+            "YW1lGAEgASgJEgoKAmlkGAIgASgFEg0KBWVtYWlsGAMgASgJEisKBXBob25l", 
+            "GAQgAygLMhwudHV0b3JpYWwuUGVyc29uLlBob25lTnVtYmVyGkcKC1Bob25l", 
+            "TnVtYmVyEg4KBm51bWJlchgBIAEoCRIoCgR0eXBlGAIgASgOMhoudHV0b3Jp", 
+            "YWwuUGVyc29uLlBob25lVHlwZSIrCglQaG9uZVR5cGUSCgoGTU9CSUxFEAAS", 
+            "CAoESE9NRRABEggKBFdPUksQAiIvCgtBZGRyZXNzQm9vaxIgCgZwZXJzb24Y", 
+            "ASADKAsyEC50dXRvcmlhbC5QZXJzb25CUAoUY29tLmV4YW1wbGUudHV0b3Jp", 
+            "YWxCEUFkZHJlc3NCb29rUHJvdG9zqgIkR29vZ2xlLlByb3RvYnVmLkV4YW1w", 
+          "bGVzLkFkZHJlc3NCb29rYgZwcm90bzM="));
+      descriptor = pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
           new pbd::FileDescriptor[] {
-          }, assigner);
+          });
+      internal__static_tutorial_Person__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.Examples.AddressBook.Person), descriptor.MessageTypes[0],
+              new string[] { "Name", "Id", "Email", "Phone", });
+      internal__static_tutorial_Person_PhoneNumber__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber), descriptor.MessageTypes[0].NestedTypes[0],
+              new string[] { "Number", "Type", });
+      internal__static_tutorial_AddressBook__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.Examples.AddressBook.AddressBook), descriptor.MessageTypes[1],
+              new string[] { "Person", });
     }
     #endregion
 
@@ -69,19 +60,23 @@
     private static readonly string[] _fieldNames = new string[] { "email", "id", "name", "phone" };
     private static readonly uint[] _fieldTags = new uint[] { 26, 16, 10, 34 };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.Examples.AddressBook.Addressbook.internal__static_tutorial_Person__Descriptor; }
+      get { return global::Google.Protobuf.Examples.AddressBook.Addressbook.Descriptor.MessageTypes[0]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<Person> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.Examples.AddressBook.Addressbook.internal__static_tutorial_Person__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public Person() { }
+    public Person() {
+      OnConstruction();
+    }
 
-    public Person(Person other) {
+    partial void OnConstruction();
+
+    public Person(Person other) : this() {
       name_ = other.name_;
       id_ = other.id_;
       email_ = other.email_;
@@ -260,19 +255,23 @@
         private static readonly string[] _fieldNames = new string[] { "number", "type" };
         private static readonly uint[] _fieldTags = new uint[] { 10, 16 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.Examples.AddressBook.Addressbook.internal__static_tutorial_Person_PhoneNumber__Descriptor; }
+          get { return global::Google.Protobuf.Examples.AddressBook.Person.Descriptor.NestedTypes[0]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<PhoneNumber> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.Examples.AddressBook.Addressbook.internal__static_tutorial_Person_PhoneNumber__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public PhoneNumber() { }
+        public PhoneNumber() {
+          OnConstruction();
+        }
 
-        public PhoneNumber(PhoneNumber other) {
+        partial void OnConstruction();
+
+        public PhoneNumber(PhoneNumber other) : this() {
           number_ = other.number_;
           type_ = other.type_;
         }
@@ -299,7 +298,7 @@
         }
 
         public const int TypeFieldNumber = 2;
-        private global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType type_ = global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType.HOME;
+        private global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType type_ = global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType.MOBILE;
         public global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType Type {
           get { return type_; }
           set {
@@ -327,7 +326,7 @@
         public override int GetHashCode() {
           int hash = 1;
           if (Number.Length != 0) hash ^= Number.GetHashCode();
-          if (Type != global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType.HOME) hash ^= Type.GetHashCode();
+          if (Type != global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType.MOBILE) hash ^= Type.GetHashCode();
           return hash;
         }
 
@@ -336,7 +335,7 @@
             output.WriteRawTag(10);
             output.WriteString(Number);
           }
-          if (Type != global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType.HOME) {
+          if (Type != global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType.MOBILE) {
             output.WriteRawTag(16);
             output.WriteEnum((int) Type);
           }
@@ -347,7 +346,7 @@
           if (Number.Length != 0) {
             size += 1 + pb::CodedOutputStream.ComputeStringSize(Number);
           }
-          if (Type != global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType.HOME) {
+          if (Type != global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType.MOBILE) {
             size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Type);
           }
           return size;
@@ -360,7 +359,7 @@
           if (other.Number.Length != 0) {
             Number = other.Number;
           }
-          if (other.Type != global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType.HOME) {
+          if (other.Type != global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType.MOBILE) {
             Type = other.Type;
           }
         }
@@ -403,19 +402,23 @@
     private static readonly string[] _fieldNames = new string[] { "person" };
     private static readonly uint[] _fieldTags = new uint[] { 10 };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.Examples.AddressBook.Addressbook.internal__static_tutorial_AddressBook__Descriptor; }
+      get { return global::Google.Protobuf.Examples.AddressBook.Addressbook.Descriptor.MessageTypes[1]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<AddressBook> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.Examples.AddressBook.Addressbook.internal__static_tutorial_AddressBook__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public AddressBook() { }
+    public AddressBook() {
+      OnConstruction();
+    }
 
-    public AddressBook(AddressBook other) {
+    partial void OnConstruction();
+
+    public AddressBook(AddressBook other) : this() {
       person_ = other.person_.Clone();
     }
 
diff --git a/csharp/src/ProtocolBuffers.Test/Collections/MapFieldTest.cs b/csharp/src/ProtocolBuffers.Test/Collections/MapFieldTest.cs
index 75f8ff2..d43bed3 100644
--- a/csharp/src/ProtocolBuffers.Test/Collections/MapFieldTest.cs
+++ b/csharp/src/ProtocolBuffers.Test/Collections/MapFieldTest.cs
@@ -34,6 +34,8 @@
 using System.Collections.Generic;
 using Google.Protobuf.TestProtos;
 using NUnit.Framework;
+using System.Collections;
+using System.Linq;
 
 namespace Google.Protobuf.Collections
 {
@@ -54,6 +56,18 @@
         }
 
         [Test]
+        public void Freeze_Idempotent()
+        {
+            var message = new ForeignMessage { C = 20 };
+            var map = new MapField<string, ForeignMessage> { { "x", message } };
+            Assert.IsFalse(map.IsFrozen);
+            map.Freeze();
+            Assert.IsTrue(message.IsFrozen);
+            map.Freeze();
+            Assert.IsTrue(message.IsFrozen);
+        }
+
+        [Test]
         public void Freeze_PreventsMutation()
         {
             var map = new MapField<string, string>();
@@ -188,6 +202,15 @@
         }
 
         [Test]
+        public void Equality_Simple()
+        {
+            var map = new MapField<string, string>();
+            EqualityTester.AssertEquality(map, map);
+            EqualityTester.AssertInequality(map, null);
+            Assert.IsFalse(map.Equals(new object()));
+        }
+
+        [Test]
         public void EqualityIsValueSensitive()
         {
             // Note: Without some care, it's a little easier than one might
@@ -287,7 +310,8 @@
             Assert.IsFalse(map.Remove("missing"));
             Assert.AreEqual(1, map.Count);
             Assert.IsTrue(map.Remove("foo"));
-            Assert.AreEqual(0, map.Count);           
+            Assert.AreEqual(0, map.Count);
+            Assert.Throws<ArgumentNullException>(() => map.Remove(null));
         }
 
         [Test]
@@ -346,6 +370,164 @@
             Assert.AreEqual("z", map["x"]);
         }
 
+        [Test]
+        public void GetEnumerator_NonGeneric()
+        {
+            IEnumerable map = new MapField<string, string> { { "x", "y" } };
+            CollectionAssert.AreEqual(new[] { new KeyValuePair<string, string>("x", "y") },
+                map.Cast<object>().ToList());
+        }
+
+        // Test for the explicitly-implemented non-generic IDictionary interface
+        [Test]
+        public void IDictionary_GetEnumerator()
+        {
+            IDictionary map = new MapField<string, string> { { "x", "y" } };
+            var enumerator = map.GetEnumerator();
+
+            // Commented assertions show an ideal situation - it looks like
+            // the LinkedList enumerator doesn't throw when you ask for the current entry
+            // at an inappropriate time; fixing this would be more work than it's worth.
+            // Assert.Throws<InvalidOperationException>(() => enumerator.Current.GetHashCode());
+            Assert.IsTrue(enumerator.MoveNext());
+            Assert.AreEqual("x", enumerator.Key);
+            Assert.AreEqual("y", enumerator.Value);
+            Assert.AreEqual(new DictionaryEntry("x", "y"), enumerator.Current);
+            Assert.AreEqual(new DictionaryEntry("x", "y"), enumerator.Entry);
+            Assert.IsFalse(enumerator.MoveNext());
+            // Assert.Throws<InvalidOperationException>(() => enumerator.Current.GetHashCode());
+            enumerator.Reset();
+            // Assert.Throws<InvalidOperationException>(() => enumerator.Current.GetHashCode());
+            Assert.IsTrue(enumerator.MoveNext());
+            Assert.AreEqual("x", enumerator.Key); // Assume the rest are okay
+        }
+
+        [Test]
+        public void IDictionary_Add()
+        {
+            var map = new MapField<string, string> { { "x", "y" } };
+            IDictionary dictionary = map;
+            dictionary.Add("a", "b");
+            Assert.AreEqual("b", map["a"]);
+            Assert.Throws<ArgumentException>(() => dictionary.Add("a", "duplicate"));
+            Assert.Throws<InvalidCastException>(() => dictionary.Add(new object(), "key is bad"));
+            Assert.Throws<InvalidCastException>(() => dictionary.Add("value is bad", new object()));
+        }
+
+        [Test]
+        public void IDictionary_Contains()
+        {
+            var map = new MapField<string, string> { { "x", "y" } };
+            IDictionary dictionary = map;
+
+            Assert.IsFalse(dictionary.Contains("a"));
+            Assert.IsFalse(dictionary.Contains(5));
+            // Surprising, but IDictionary.Contains is only about keys.
+            Assert.IsFalse(dictionary.Contains(new DictionaryEntry("x", "y")));
+            Assert.IsTrue(dictionary.Contains("x"));
+        }
+
+        [Test]
+        public void IDictionary_Remove()
+        {
+            var map = new MapField<string, string> { { "x", "y" } };
+            IDictionary dictionary = map;
+            dictionary.Remove("a");
+            Assert.AreEqual(1, dictionary.Count);
+            dictionary.Remove(5);
+            Assert.AreEqual(1, dictionary.Count);
+            dictionary.Remove(new DictionaryEntry("x", "y"));
+            Assert.AreEqual(1, dictionary.Count);
+            dictionary.Remove("x");
+            Assert.AreEqual(0, dictionary.Count);
+            Assert.Throws<ArgumentNullException>(() => dictionary.Remove(null));
+
+            map.Freeze();
+            // Call should fail even though it clearly doesn't contain 5 as a key.
+            Assert.Throws<InvalidOperationException>(() => dictionary.Remove(5));
+        }
+
+        [Test]
+        public void IDictionary_CopyTo()
+        {
+            var map = new MapField<string, string> { { "x", "y" } };
+            IDictionary dictionary = map;
+            var array = new DictionaryEntry[3];
+            dictionary.CopyTo(array, 1);
+            CollectionAssert.AreEqual(new[] { default(DictionaryEntry), new DictionaryEntry("x", "y"), default(DictionaryEntry) },
+                array);
+            var objectArray = new object[3];
+            dictionary.CopyTo(objectArray, 1);
+            CollectionAssert.AreEqual(new object[] { null, new DictionaryEntry("x", "y"), null },
+                objectArray);
+        }
+
+        [Test]
+        public void IDictionary_IsFixedSize()
+        {
+            var map = new MapField<string, string> { { "x", "y" } };
+            IDictionary dictionary = map;
+            Assert.IsFalse(dictionary.IsFixedSize);
+            map.Freeze();
+            Assert.IsTrue(dictionary.IsFixedSize);
+        }
+
+        [Test]
+        public void IDictionary_Keys()
+        {
+            IDictionary dictionary = new MapField<string, string> { { "x", "y" } };
+            CollectionAssert.AreEqual(new[] { "x" }, dictionary.Keys);
+        }
+
+        [Test]
+        public void IDictionary_Values()
+        {
+            IDictionary dictionary = new MapField<string, string> { { "x", "y" } };
+            CollectionAssert.AreEqual(new[] { "y" }, dictionary.Values);
+        }
+
+        [Test]
+        public void IDictionary_IsSynchronized()
+        {
+            IDictionary dictionary = new MapField<string, string> { { "x", "y" } };
+            Assert.IsFalse(dictionary.IsSynchronized);
+        }
+
+        [Test]
+        public void IDictionary_SyncRoot()
+        {
+            IDictionary dictionary = new MapField<string, string> { { "x", "y" } };
+            Assert.AreSame(dictionary, dictionary.SyncRoot);
+        }
+
+        [Test]
+        public void IDictionary_Indexer_Get()
+        {
+            IDictionary dictionary = new MapField<string, string> { { "x", "y" } };
+            Assert.AreEqual("y", dictionary["x"]);
+            Assert.IsNull(dictionary["a"]);
+            Assert.IsNull(dictionary[5]);
+            Assert.Throws<ArgumentNullException>(() => dictionary[null].GetHashCode());
+        }
+
+        [Test]
+        public void IDictionary_Indexer_Set()
+        {
+            var map = new MapField<string, string> { { "x", "y" } };
+            IDictionary dictionary = map;
+            map["a"] = "b";
+            Assert.AreEqual("b", map["a"]);
+            map["a"] = "c";
+            Assert.AreEqual("c", map["a"]);
+            Assert.Throws<InvalidCastException>(() => dictionary[5] = "x");
+            Assert.Throws<InvalidCastException>(() => dictionary["x"] = 5);
+            Assert.Throws<ArgumentNullException>(() => dictionary[null] = "z");
+            Assert.Throws<ArgumentNullException>(() => dictionary["x"] = null);
+            map.Freeze();
+            // Note: Not InvalidOperationException.
+            Assert.Throws<NotSupportedException>(() => dictionary["a"] = "c");
+        }
+
         private static KeyValuePair<TKey, TValue> NewKeyValuePair<TKey, TValue>(TKey key, TValue value)
         {
             return new KeyValuePair<TKey, TValue>(key, value);
diff --git a/csharp/src/ProtocolBuffers.Test/Collections/RepeatedFieldTest.cs b/csharp/src/ProtocolBuffers.Test/Collections/RepeatedFieldTest.cs
index 988801b..6eff868 100644
--- a/csharp/src/ProtocolBuffers.Test/Collections/RepeatedFieldTest.cs
+++ b/csharp/src/ProtocolBuffers.Test/Collections/RepeatedFieldTest.cs
@@ -31,9 +31,11 @@
 #endregion
 
 using System;
+using System.Collections;
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
+using System.Text;
 using Google.Protobuf.TestProtos;
 using NUnit.Framework;
 
@@ -83,6 +85,115 @@
         }
 
         [Test]
+        public void RemoveAt_Valid()
+        {
+            var list = new RepeatedField<string> { "first", "second", "third" };
+            list.RemoveAt(1);
+            CollectionAssert.AreEqual(new[] { "first", "third" }, list);
+            // Just check that these don't throw...
+            list.RemoveAt(list.Count - 1); // Now the count will be 1...
+            list.RemoveAt(0);
+            Assert.AreEqual(0, list.Count);
+        }
+
+        [Test]
+        public void RemoveAt_Invalid()
+        {
+            var list = new RepeatedField<string> { "first", "second", "third" };
+            Assert.Throws<ArgumentOutOfRangeException>(() => list.RemoveAt(-1));
+            Assert.Throws<ArgumentOutOfRangeException>(() => list.RemoveAt(3));
+        }
+
+        [Test]
+        public void Insert_Valid()
+        {
+            var list = new RepeatedField<string> { "first", "second" };
+            list.Insert(1, "middle");
+            CollectionAssert.AreEqual(new[] { "first", "middle", "second" }, list);
+            list.Insert(3, "end");
+            CollectionAssert.AreEqual(new[] { "first", "middle", "second", "end" }, list);
+            list.Insert(0, "start");
+            CollectionAssert.AreEqual(new[] { "start", "first", "middle", "second", "end" }, list);
+        }
+
+        [Test]
+        public void Insert_Invalid()
+        {
+            var list = new RepeatedField<string> { "first", "second" };
+            Assert.Throws<ArgumentOutOfRangeException>(() => list.Insert(-1, "foo"));
+            Assert.Throws<ArgumentOutOfRangeException>(() => list.Insert(3, "foo"));
+            Assert.Throws<ArgumentNullException>(() => list.Insert(0, null));
+        }
+
+        [Test]
+        public void Equals_RepeatedField()
+        {
+            var list = new RepeatedField<string> { "first", "second" };
+            Assert.IsFalse(list.Equals((RepeatedField<string>) null));
+            Assert.IsTrue(list.Equals(list));
+            Assert.IsFalse(list.Equals(new RepeatedField<string> { "first", "third" }));
+            Assert.IsFalse(list.Equals(new RepeatedField<string> { "first" }));
+            Assert.IsTrue(list.Equals(new RepeatedField<string> { "first", "second" }));
+        }
+
+        [Test]
+        public void Equals_Object()
+        {
+            var list = new RepeatedField<string> { "first", "second" };
+            Assert.IsFalse(list.Equals((object) null));
+            Assert.IsTrue(list.Equals((object) list));
+            Assert.IsFalse(list.Equals((object) new RepeatedField<string> { "first", "third" }));
+            Assert.IsFalse(list.Equals((object) new RepeatedField<string> { "first" }));
+            Assert.IsTrue(list.Equals((object) new RepeatedField<string> { "first", "second" }));
+            Assert.IsFalse(list.Equals(new object()));
+        }
+
+        [Test]
+        public void GetEnumerator_GenericInterface()
+        {
+            IEnumerable<string> list = new RepeatedField<string> { "first", "second" };
+            // Select gets rid of the optimizations in ToList...
+            CollectionAssert.AreEqual(new[] { "first", "second" }, list.Select(x => x).ToList());
+        }
+
+        [Test]
+        public void GetEnumerator_NonGenericInterface()
+        {
+            IEnumerable list = new RepeatedField<string> { "first", "second" };
+            CollectionAssert.AreEqual(new[] { "first", "second" }, list.Cast<object>().ToList());
+        }
+
+        [Test]
+        public void CopyTo()
+        {
+            var list = new RepeatedField<string> { "first", "second" };
+            string[] stringArray = new string[4];
+            list.CopyTo(stringArray, 1);
+            CollectionAssert.AreEqual(new[] { null, "first", "second", null }, stringArray);
+        }
+
+        [Test]
+        public void Indexer_Get()
+        {
+            var list = new RepeatedField<string> { "first", "second" };
+            Assert.AreEqual("first", list[0]);
+            Assert.AreEqual("second", list[1]);
+            Assert.Throws<ArgumentOutOfRangeException>(() => list[-1].GetHashCode());
+            Assert.Throws<ArgumentOutOfRangeException>(() => list[2].GetHashCode());
+        }
+
+        [Test]
+        public void Indexer_Set()
+        {
+            var list = new RepeatedField<string> { "first", "second" };
+            list[0] = "changed";
+            Assert.AreEqual("changed", list[0]);
+            Assert.Throws<ArgumentNullException>(() => list[0] = null);
+            Assert.Throws<ArgumentOutOfRangeException>(() => list[-1] = "bad");
+            Assert.Throws<ArgumentOutOfRangeException>(() => list[2] = "bad");
+        }
+
+        [Test]
         public void Freeze_FreezesElements()
         {
             var list = new RepeatedField<TestAllTypes> { new TestAllTypes() };
@@ -125,6 +236,27 @@
         }
 
         [Test]
+        public void Enumerator()
+        {
+            var list = new RepeatedField<string> { "first", "second" };
+            using (var enumerator = list.GetEnumerator())
+            {
+                Assert.Throws<InvalidOperationException>(() => enumerator.Current.GetHashCode());
+                Assert.IsTrue(enumerator.MoveNext());
+                Assert.AreEqual("first", enumerator.Current);
+                Assert.IsTrue(enumerator.MoveNext());
+                Assert.AreEqual("second", enumerator.Current);
+                Assert.IsFalse(enumerator.MoveNext());
+                Assert.Throws<InvalidOperationException>(() => enumerator.Current.GetHashCode());
+                Assert.IsFalse(enumerator.MoveNext());
+                enumerator.Reset();
+                Assert.Throws<InvalidOperationException>(() => enumerator.Current.GetHashCode());
+                Assert.IsTrue(enumerator.MoveNext());
+                Assert.AreEqual("first", enumerator.Current);
+            }
+        }
+
+        [Test]
         public void AddEntriesFrom_PackedInt32()
         {
             uint packedTag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
@@ -309,6 +441,42 @@
             Assert.IsTrue(input.IsAtEnd);
         }
 
+        [Test]
+        public void CalculateSize_VariableSizeNonPacked()
+        {
+            var list = new RepeatedField<int> { 1, 500, 1 };
+            var tag = WireFormat.MakeTag(1, WireFormat.WireType.Varint);
+            // 2 bytes for the first entry, 3 bytes for the second, 2 bytes for the third
+            Assert.AreEqual(7, list.CalculateSize(FieldCodec.ForInt32(tag)));
+        }
+
+        [Test]
+        public void CalculateSize_FixedSizeNonPacked()
+        {
+            var list = new RepeatedField<int> { 1, 500, 1 };
+            var tag = WireFormat.MakeTag(1, WireFormat.WireType.Fixed32);
+            // 5 bytes for the each entry
+            Assert.AreEqual(15, list.CalculateSize(FieldCodec.ForSFixed32(tag)));
+        }
+
+        [Test]
+        public void CalculateSize_VariableSizePacked()
+        {
+            var list = new RepeatedField<int> { 1, 500, 1};
+            var tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited);
+            // 1 byte for the tag, 1 byte for the length,
+            // 1 byte for the first entry, 2 bytes for the second, 1 byte for the third
+            Assert.AreEqual(6, list.CalculateSize(FieldCodec.ForInt32(tag)));
+        }
+
+        [Test]
+        public void CalculateSize_FixedSizePacked()
+        {
+            var list = new RepeatedField<int> { 1, 500, 1 };
+            var tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited);
+            // 1 byte for the tag, 1 byte for the length, 4 bytes per entry
+            Assert.AreEqual(14, list.CalculateSize(FieldCodec.ForSFixed32(tag)));
+        }
 
         [Test]
         public void TestNegativeEnumArray()
@@ -378,5 +546,100 @@
             Assert.AreEqual(((SampleEnum)(-4)), values[4]);
             Assert.AreEqual(((SampleEnum)(-5)), values[5]);
         }
+
+        // Fairly perfunctory tests for the non-generic IList implementation
+        [Test]
+        public void IList_Indexer()
+        {
+            var field = new RepeatedField<string> { "first", "second" };
+            IList list = field;
+            Assert.AreEqual("first", list[0]);
+            list[1] = "changed";
+            Assert.AreEqual("changed", field[1]);
+        }
+
+        [Test]
+        public void IList_Contains()
+        {
+            IList list = new RepeatedField<string> { "first", "second" };
+            Assert.IsTrue(list.Contains("second"));
+            Assert.IsFalse(list.Contains("third"));
+            Assert.IsFalse(list.Contains(new object()));
+        }
+
+        [Test]
+        public void IList_Add()
+        {
+            IList list = new RepeatedField<string> { "first", "second" };
+            list.Add("third");
+            CollectionAssert.AreEqual(new[] { "first", "second", "third" }, list);
+        }
+
+        [Test]
+        public void IList_Remove()
+        {
+            IList list = new RepeatedField<string> { "first", "second" };
+            list.Remove("third"); // No-op, no exception
+            list.Remove(new object()); // No-op, no exception
+            list.Remove("first");
+            CollectionAssert.AreEqual(new[] { "second" }, list);
+        }
+
+        [Test]
+        public void IList_IsFixedSize()
+        {
+            var field = new RepeatedField<string> { "first", "second" };
+            IList list = field;
+            Assert.IsFalse(list.IsFixedSize);
+            field.Freeze();
+            Assert.IsTrue(list.IsFixedSize);
+        }
+
+        [Test]
+        public void IList_IndexOf()
+        {
+            IList list = new RepeatedField<string> { "first", "second" };
+            Assert.AreEqual(1, list.IndexOf("second"));
+            Assert.AreEqual(-1, list.IndexOf("third"));
+            Assert.AreEqual(-1, list.IndexOf(new object()));
+        }
+
+        [Test]
+        public void IList_SyncRoot()
+        {
+            IList list = new RepeatedField<string> { "first", "second" };
+            Assert.AreSame(list, list.SyncRoot);
+        }
+
+        [Test]
+        public void IList_CopyTo()
+        {
+            IList list = new RepeatedField<string> { "first", "second" };
+            string[] stringArray = new string[4];
+            list.CopyTo(stringArray, 1);
+            CollectionAssert.AreEqual(new[] { null, "first",  "second", null }, stringArray);
+
+            object[] objectArray = new object[4];
+            list.CopyTo(objectArray, 1);
+            CollectionAssert.AreEqual(new[] { null, "first", "second", null }, objectArray);
+
+            Assert.Throws<ArrayTypeMismatchException>(() => list.CopyTo(new StringBuilder[4], 1));
+            Assert.Throws<ArrayTypeMismatchException>(() => list.CopyTo(new int[4], 1));
+        }
+
+        [Test]
+        public void IList_IsSynchronized()
+        {
+            IList list = new RepeatedField<string> { "first", "second" };
+            Assert.IsFalse(list.IsSynchronized);
+        }
+
+        [Test]
+        public void IList_Insert()
+        {
+            IList list = new RepeatedField<string> { "first", "second" };
+            list.Insert(1, "middle");
+            CollectionAssert.AreEqual(new[] { "first", "middle", "second" }, list);
+        }
     }
 }
diff --git a/csharp/src/ProtocolBuffers.Test/DescriptorsTest.cs b/csharp/src/ProtocolBuffers.Test/DescriptorsTest.cs
index e0fef91..d5c622b 100644
--- a/csharp/src/ProtocolBuffers.Test/DescriptorsTest.cs
+++ b/csharp/src/ProtocolBuffers.Test/DescriptorsTest.cs
@@ -30,6 +30,8 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

 #endregion

 

+using System.Linq;

+using Google.Protobuf.DescriptorProtos;

 using Google.Protobuf.Descriptors;

 using Google.Protobuf.TestProtos;

 using NUnit.Framework;

@@ -50,7 +52,7 @@
             Assert.AreEqual("google/protobuf/unittest_proto3.proto", file.Name);

             Assert.AreEqual("protobuf_unittest", file.Package);

 

-            Assert.AreEqual("UnittestProto", file.Options.JavaOuterClassname);

+            Assert.AreEqual("UnittestProto", file.Proto.Options.JavaOuterClassname);

             Assert.AreEqual("google/protobuf/unittest_proto3.proto", file.Proto.Name);

 

             // unittest.proto doesn't have any public imports, but unittest_import.proto does.

@@ -92,7 +94,7 @@
             Assert.AreEqual("protobuf_unittest.TestAllTypes", messageType.FullName);

             Assert.AreEqual(UnittestProto3.Descriptor, messageType.File);

             Assert.IsNull(messageType.ContainingType);

-            Assert.IsNull(messageType.Options);

+            Assert.IsNull(messageType.Proto.Options);

 

             Assert.AreEqual("TestAllTypes", messageType.Name);

 

@@ -143,7 +145,7 @@
             Assert.AreEqual(messageType, primitiveField.ContainingType);

             Assert.AreEqual(UnittestProto3.Descriptor, primitiveField.File);

             Assert.AreEqual(FieldType.Int32, primitiveField.FieldType);

-            Assert.IsNull(primitiveField.Options);

+            Assert.IsNull(primitiveField.Proto.Options);

             

             Assert.AreEqual("single_nested_enum", enumField.Name);

             Assert.AreEqual(FieldType.Enum, enumField.FieldType);

@@ -177,7 +179,7 @@
             Assert.AreEqual("protobuf_unittest.ForeignEnum", enumType.FullName);

             Assert.AreEqual(UnittestProto3.Descriptor, enumType.File);

             Assert.Null(enumType.ContainingType);

-            Assert.Null(enumType.Options);

+            Assert.Null(enumType.Proto.Options);

 

             Assert.AreEqual("NestedEnum", nestedType.Name);

             Assert.AreEqual("protobuf_unittest.TestAllTypes.NestedEnum",

@@ -197,5 +199,27 @@
                 Assert.AreEqual(i, enumType.Values[i].Index);

             }

         }

+

+        [Test]

+        public void OneofDescriptor()

+        {

+            OneofDescriptor descriptor = TestAllTypes.Descriptor.FindDescriptor<OneofDescriptor>("oneof_field");

+            Assert.AreEqual("oneof_field", descriptor.Name);

+            Assert.AreEqual("protobuf_unittest.TestAllTypes.oneof_field", descriptor.FullName);

+

+            var expectedFields = new[] {

+                TestAllTypes.OneofBytesFieldNumber,

+                TestAllTypes.OneofNestedMessageFieldNumber,

+                TestAllTypes.OneofStringFieldNumber,

+                TestAllTypes.OneofUint32FieldNumber }

+                .Select(fieldNumber => TestAllTypes.Descriptor.FindFieldByNumber(fieldNumber))

+                .ToList();

+            foreach (var field in expectedFields)

+            {

+                Assert.AreSame(descriptor, field.ContainingOneof);

+            }

+

+            CollectionAssert.AreEquivalent(expectedFields, descriptor.Fields);

+        }

     }

 }
\ No newline at end of file
diff --git a/csharp/src/ProtocolBuffers.Test/EqualityTester.cs b/csharp/src/ProtocolBuffers.Test/EqualityTester.cs
index b372443..a669bab 100644
--- a/csharp/src/ProtocolBuffers.Test/EqualityTester.cs
+++ b/csharp/src/ProtocolBuffers.Test/EqualityTester.cs
@@ -45,15 +45,20 @@
         public static void AssertEquality<T>(T first, T second) where T : IEquatable<T>
         {
             Assert.IsTrue(first.Equals(second));
+            Assert.IsTrue(first.Equals((object) second));
             Assert.AreEqual(first.GetHashCode(), second.GetHashCode());
         }
 
         public static void AssertInequality<T>(T first, T second) where T : IEquatable<T>
         {
             Assert.IsFalse(first.Equals(second));
+            Assert.IsFalse(first.Equals((object) second));
             // While this isn't a requirement, the chances of this test failing due to
             // coincidence rather than a bug are very small.
-            Assert.AreNotEqual(first.GetHashCode(), second.GetHashCode());
+            if (first != null && second != null)
+            {
+                Assert.AreNotEqual(first.GetHashCode(), second.GetHashCode());
+            }
         }
     }
 }
diff --git a/csharp/src/ProtocolBuffers.Test/FieldCodecTest.cs b/csharp/src/ProtocolBuffers.Test/FieldCodecTest.cs
index a14040d..c6ed2a2 100644
--- a/csharp/src/ProtocolBuffers.Test/FieldCodecTest.cs
+++ b/csharp/src/ProtocolBuffers.Test/FieldCodecTest.cs
@@ -86,12 +86,22 @@
             codec.TestDefaultValue();
         }
 
+        [Test, TestCaseSource("Codecs")]
+        public void FixedSize(ICodecTestData codec)
+        {
+            codec.TestFixedSize();
+        }
+
+        // This is ugly, but it means we can have a non-generic interface.
+        // It feels like NUnit should support this better, but I don't know
+        // of any better ways right now.
         public interface ICodecTestData
         {
             void TestRoundTripRaw();
             void TestRoundTripWithTag();
             void TestCalculateSizeWithTag();
             void TestDefaultValue();
+            void TestFixedSize();
         }
 
         public class FieldCodecTestData<T> : ICodecTestData
@@ -169,6 +179,11 @@
                 }
             }
 
+            public void TestFixedSize()
+            {
+                Assert.AreEqual(name.Contains("Fixed"), codec.FixedSize != 0);
+            }
+
             public override string ToString()
             {
                 return name;
diff --git a/csharp/src/ProtocolBuffers.Test/GeneratedMessageTest.cs b/csharp/src/ProtocolBuffers.Test/GeneratedMessageTest.cs
index e98ffab..8cee982 100644
--- a/csharp/src/ProtocolBuffers.Test/GeneratedMessageTest.cs
+++ b/csharp/src/ProtocolBuffers.Test/GeneratedMessageTest.cs
@@ -29,11 +29,13 @@
 // (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.IO;

 using Google.Protobuf.TestProtos;

 using NUnit.Framework;

+using System.Collections;

+using System.Collections.Generic;

 

 namespace Google.Protobuf

 {

@@ -595,5 +597,142 @@
             Assert.AreEqual(message, message2);

             Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, message2.OneofFieldCase);

         }

+

+        // TODO: Consider moving these tests to a separate reflection test - although they do require generated messages.

+

+        [Test]

+        public void Reflection_GetValue()

+        {

+            var message = SampleMessages.CreateFullTestAllTypes();

+            var fields = message.Fields;

+            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));

+            Assert.AreEqual(message.SingleFixed32, fields[TestAllTypes.SingleFixed32FieldNumber].GetValue(message));

+            Assert.AreEqual(message.SingleFixed64, fields[TestAllTypes.SingleFixed64FieldNumber].GetValue(message));

+            Assert.AreEqual(message.SingleFloat, fields[TestAllTypes.SingleFloatFieldNumber].GetValue(message));

+            Assert.AreEqual(message.SingleForeignEnum, fields[TestAllTypes.SingleForeignEnumFieldNumber].GetValue(message));

+            Assert.AreEqual(message.SingleForeignMessage, fields[TestAllTypes.SingleForeignMessageFieldNumber].GetValue(message));

+            Assert.AreEqual(message.SingleImportEnum, fields[TestAllTypes.SingleImportEnumFieldNumber].GetValue(message));

+            Assert.AreEqual(message.SingleImportMessage, fields[TestAllTypes.SingleImportMessageFieldNumber].GetValue(message));

+            Assert.AreEqual(message.SingleInt32, fields[TestAllTypes.SingleInt32FieldNumber].GetValue(message));

+            Assert.AreEqual(message.SingleInt64, fields[TestAllTypes.SingleInt64FieldNumber].GetValue(message));

+            Assert.AreEqual(message.SingleNestedEnum, fields[TestAllTypes.SingleNestedEnumFieldNumber].GetValue(message));

+            Assert.AreEqual(message.SingleNestedMessage, fields[TestAllTypes.SingleNestedMessageFieldNumber].GetValue(message));

+            Assert.AreEqual(message.SinglePublicImportMessage, fields[TestAllTypes.SinglePublicImportMessageFieldNumber].GetValue(message));

+            Assert.AreEqual(message.SingleSint32, fields[TestAllTypes.SingleSint32FieldNumber].GetValue(message));

+            Assert.AreEqual(message.SingleSint64, fields[TestAllTypes.SingleSint64FieldNumber].GetValue(message));

+            Assert.AreEqual(message.SingleString, fields[TestAllTypes.SingleStringFieldNumber].GetValue(message));

+            Assert.AreEqual(message.SingleSfixed32, fields[TestAllTypes.SingleSfixed32FieldNumber].GetValue(message));

+            Assert.AreEqual(message.SingleSfixed64, fields[TestAllTypes.SingleSfixed64FieldNumber].GetValue(message));

+            Assert.AreEqual(message.SingleUint32, fields[TestAllTypes.SingleUint32FieldNumber].GetValue(message));

+            Assert.AreEqual(message.SingleUint64, fields[TestAllTypes.SingleUint64FieldNumber].GetValue(message));

+            Assert.AreEqual(message.OneofBytes, fields[TestAllTypes.OneofBytesFieldNumber].GetValue(message));

+            Assert.AreEqual(message.OneofString, fields[TestAllTypes.OneofStringFieldNumber].GetValue(message));

+            Assert.AreEqual(message.OneofNestedMessage, fields[TestAllTypes.OneofNestedMessageFieldNumber].GetValue(message));

+            Assert.AreEqual(message.OneofUint32, fields[TestAllTypes.OneofUint32FieldNumber].GetValue(message));

+

+            // Just one example for repeated fields - they're all just returning the list

+            var list = (IList)fields[TestAllTypes.RepeatedInt32FieldNumber].GetValue(message);

+            Assert.AreEqual(message.RepeatedInt32, list);

+            Assert.AreEqual(message.RepeatedInt32[0], list[0]); // Just in case there was any doubt...

+

+            // Just a single map field, for the same reason

+            var mapMessage = new TestMap { MapStringString = { { "key1", "value1" }, { "key2", "value2" } } };

+            var dictionary = (IDictionary)mapMessage.Fields[TestMap.MapStringStringFieldNumber].GetValue(mapMessage);

+            Assert.AreEqual(mapMessage.MapStringString, dictionary);

+            Assert.AreEqual("value1", dictionary["key1"]);

+        }

+

+        [Test]

+        public void Reflection_Clear()

+        {

+            var message = SampleMessages.CreateFullTestAllTypes();

+            var fields = message.Fields;

+            fields[TestAllTypes.SingleBoolFieldNumber].Clear(message);

+            fields[TestAllTypes.SingleInt32FieldNumber].Clear(message);

+            fields[TestAllTypes.SingleStringFieldNumber].Clear(message);

+            fields[TestAllTypes.SingleBytesFieldNumber].Clear(message);

+            fields[TestAllTypes.SingleForeignEnumFieldNumber].Clear(message);

+            fields[TestAllTypes.SingleForeignMessageFieldNumber].Clear(message);

+            fields[TestAllTypes.RepeatedDoubleFieldNumber].Clear(message);

+

+            var expected = new TestAllTypes(SampleMessages.CreateFullTestAllTypes())

+            {

+                SingleBool = false,

+                SingleInt32 = 0,

+                SingleString = "",

+                SingleBytes = ByteString.Empty,

+                SingleForeignEnum = 0,

+                SingleForeignMessage = null,

+            };

+            expected.RepeatedDouble.Clear();

+

+            Assert.AreEqual(expected, message);

+

+            // Separately, maps.

+            var mapMessage = new TestMap { MapStringString = { { "key1", "value1" }, { "key2", "value2" } } };

+            mapMessage.Fields[TestMap.MapStringStringFieldNumber].Clear(mapMessage);

+            Assert.AreEqual(0, mapMessage.MapStringString.Count);

+        }

+

+        [Test]

+        public void Reflection_SetValue_SingleFields()

+        {

+            // Just a sample (primitives, messages, enums, strings, byte strings)

+            var message = SampleMessages.CreateFullTestAllTypes();

+            var fields = message.Fields;

+            fields[TestAllTypes.SingleBoolFieldNumber].SetValue(message, false);

+            fields[TestAllTypes.SingleInt32FieldNumber].SetValue(message, 500);

+            fields[TestAllTypes.SingleStringFieldNumber].SetValue(message, "It's a string");

+            fields[TestAllTypes.SingleBytesFieldNumber].SetValue(message, ByteString.CopyFrom(99, 98, 97));

+            fields[TestAllTypes.SingleForeignEnumFieldNumber].SetValue(message, ForeignEnum.FOREIGN_FOO);

+            fields[TestAllTypes.SingleForeignMessageFieldNumber].SetValue(message, new ForeignMessage { C = 12345 });

+            fields[TestAllTypes.SingleDoubleFieldNumber].SetValue(message, 20150701.5);

+

+            var expected = new TestAllTypes(SampleMessages.CreateFullTestAllTypes())

+            {

+                SingleBool = false,

+                SingleInt32 = 500,

+                SingleString = "It's a string",

+                SingleBytes = ByteString.CopyFrom(99, 98, 97),

+                SingleForeignEnum = ForeignEnum.FOREIGN_FOO,

+                SingleForeignMessage = new ForeignMessage { C = 12345 },

+                SingleDouble = 20150701.5

+            };

+

+            Assert.AreEqual(expected, message);

+        }

+

+        [Test]

+        public void Reflection_SetValue_SingleFields_WrongType()

+        {

+            var message = SampleMessages.CreateFullTestAllTypes();

+            var fields = message.Fields;

+            Assert.Throws<InvalidCastException>(() => fields[TestAllTypes.SingleBoolFieldNumber].SetValue(message, "This isn't a bool"));

+        }

+

+        [Test]

+        public void Reflection_SetValue_MapFields()

+        {

+            var message = new TestMap();

+            var fields = message.Fields;

+            Assert.Throws<InvalidOperationException>(() => fields[TestMap.MapStringStringFieldNumber].SetValue(message, new Dictionary<string, string>()));

+        }

+

+        [Test]

+        public void Reflection_SetValue_RepeatedFields()

+        {

+            var message = SampleMessages.CreateFullTestAllTypes();

+            var fields = message.Fields;

+            Assert.Throws<InvalidOperationException>(() => fields[TestAllTypes.RepeatedDoubleFieldNumber].SetValue(message, new double[10]));

+        }

+

+        [Test]

+        public void Reflection_GetValue_IncorrectType()

+        {

+            var message = SampleMessages.CreateFullTestAllTypes();

+            Assert.Throws<InvalidCastException>(() => message.Fields[TestAllTypes.SingleBoolFieldNumber].GetValue(new TestMap()));

+        }

     }

 }

diff --git a/csharp/src/ProtocolBuffers.Test/TestProtos/MapUnittestProto3.cs b/csharp/src/ProtocolBuffers.Test/TestProtos/MapUnittestProto3.cs
index 54c8880..55434c5 100644
--- a/csharp/src/ProtocolBuffers.Test/TestProtos/MapUnittestProto3.cs
+++ b/csharp/src/ProtocolBuffers.Test/TestProtos/MapUnittestProto3.cs
@@ -13,94 +13,50 @@
   public static partial class MapUnittestProto3 {
 
     #region Static variables
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap> internal__static_protobuf_unittest_TestMap__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap_MapInt32Int32Entry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapInt32Int32Entry> internal__static_protobuf_unittest_TestMap_MapInt32Int32Entry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap_MapInt64Int64Entry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapInt64Int64Entry> internal__static_protobuf_unittest_TestMap_MapInt64Int64Entry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap_MapUint32Uint32Entry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapUint32Uint32Entry> internal__static_protobuf_unittest_TestMap_MapUint32Uint32Entry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap_MapUint64Uint64Entry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapUint64Uint64Entry> internal__static_protobuf_unittest_TestMap_MapUint64Uint64Entry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap_MapSint32Sint32Entry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapSint32Sint32Entry> internal__static_protobuf_unittest_TestMap_MapSint32Sint32Entry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap_MapSint64Sint64Entry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapSint64Sint64Entry> internal__static_protobuf_unittest_TestMap_MapSint64Sint64Entry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap_MapFixed32Fixed32Entry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapFixed32Fixed32Entry> internal__static_protobuf_unittest_TestMap_MapFixed32Fixed32Entry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap_MapFixed64Fixed64Entry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapFixed64Fixed64Entry> internal__static_protobuf_unittest_TestMap_MapFixed64Fixed64Entry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap_MapSfixed32Sfixed32Entry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapSfixed32Sfixed32Entry> internal__static_protobuf_unittest_TestMap_MapSfixed32Sfixed32Entry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap_MapSfixed64Sfixed64Entry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapSfixed64Sfixed64Entry> internal__static_protobuf_unittest_TestMap_MapSfixed64Sfixed64Entry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap_MapInt32FloatEntry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapInt32FloatEntry> internal__static_protobuf_unittest_TestMap_MapInt32FloatEntry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap_MapInt32DoubleEntry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapInt32DoubleEntry> internal__static_protobuf_unittest_TestMap_MapInt32DoubleEntry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap_MapBoolBoolEntry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapBoolBoolEntry> internal__static_protobuf_unittest_TestMap_MapBoolBoolEntry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap_MapStringStringEntry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapStringStringEntry> internal__static_protobuf_unittest_TestMap_MapStringStringEntry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap_MapInt32BytesEntry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapInt32BytesEntry> internal__static_protobuf_unittest_TestMap_MapInt32BytesEntry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap_MapInt32EnumEntry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapInt32EnumEntry> internal__static_protobuf_unittest_TestMap_MapInt32EnumEntry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap_MapInt32ForeignMessageEntry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapInt32ForeignMessageEntry> internal__static_protobuf_unittest_TestMap_MapInt32ForeignMessageEntry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMapSubmessage__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMapSubmessage> internal__static_protobuf_unittest_TestMapSubmessage__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMessageMap__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMessageMap> internal__static_protobuf_unittest_TestMessageMap__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMessageMap_MapInt32MessageEntry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMessageMap.Types.MapInt32MessageEntry> internal__static_protobuf_unittest_TestMessageMap_MapInt32MessageEntry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestSameTypeMap__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestSameTypeMap> internal__static_protobuf_unittest_TestSameTypeMap__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestSameTypeMap_Map1Entry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestSameTypeMap.Types.Map1Entry> internal__static_protobuf_unittest_TestSameTypeMap_Map1Entry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestSameTypeMap_Map2Entry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestSameTypeMap.Types.Map2Entry> internal__static_protobuf_unittest_TestSameTypeMap_Map2Entry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestArenaMap__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap> internal__static_protobuf_unittest_TestArenaMap__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestArenaMap_MapInt32Int32Entry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapInt32Int32Entry> internal__static_protobuf_unittest_TestArenaMap_MapInt32Int32Entry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestArenaMap_MapInt64Int64Entry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapInt64Int64Entry> internal__static_protobuf_unittest_TestArenaMap_MapInt64Int64Entry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestArenaMap_MapUint32Uint32Entry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapUint32Uint32Entry> internal__static_protobuf_unittest_TestArenaMap_MapUint32Uint32Entry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestArenaMap_MapUint64Uint64Entry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapUint64Uint64Entry> internal__static_protobuf_unittest_TestArenaMap_MapUint64Uint64Entry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestArenaMap_MapSint32Sint32Entry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapSint32Sint32Entry> internal__static_protobuf_unittest_TestArenaMap_MapSint32Sint32Entry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestArenaMap_MapSint64Sint64Entry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapSint64Sint64Entry> internal__static_protobuf_unittest_TestArenaMap_MapSint64Sint64Entry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestArenaMap_MapFixed32Fixed32Entry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapFixed32Fixed32Entry> internal__static_protobuf_unittest_TestArenaMap_MapFixed32Fixed32Entry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestArenaMap_MapFixed64Fixed64Entry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapFixed64Fixed64Entry> internal__static_protobuf_unittest_TestArenaMap_MapFixed64Fixed64Entry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestArenaMap_MapSfixed32Sfixed32Entry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapSfixed32Sfixed32Entry> internal__static_protobuf_unittest_TestArenaMap_MapSfixed32Sfixed32Entry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestArenaMap_MapSfixed64Sfixed64Entry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapSfixed64Sfixed64Entry> internal__static_protobuf_unittest_TestArenaMap_MapSfixed64Sfixed64Entry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestArenaMap_MapInt32FloatEntry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapInt32FloatEntry> internal__static_protobuf_unittest_TestArenaMap_MapInt32FloatEntry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestArenaMap_MapInt32DoubleEntry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapInt32DoubleEntry> internal__static_protobuf_unittest_TestArenaMap_MapInt32DoubleEntry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestArenaMap_MapBoolBoolEntry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapBoolBoolEntry> internal__static_protobuf_unittest_TestArenaMap_MapBoolBoolEntry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestArenaMap_MapInt32EnumEntry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapInt32EnumEntry> internal__static_protobuf_unittest_TestArenaMap_MapInt32EnumEntry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestArenaMap_MapInt32ForeignMessageEntry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapInt32ForeignMessageEntry> internal__static_protobuf_unittest_TestArenaMap_MapInt32ForeignMessageEntry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_MessageContainingEnumCalledType__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType> internal__static_protobuf_unittest_MessageContainingEnumCalledType__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_MessageContainingEnumCalledType_TypeEntry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType.Types.TypeEntry> internal__static_protobuf_unittest_MessageContainingEnumCalledType_TypeEntry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_MessageContainingMapCalledEntry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.MessageContainingMapCalledEntry> internal__static_protobuf_unittest_MessageContainingMapCalledEntry__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_MessageContainingMapCalledEntry_EntryEntry__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.MessageContainingMapCalledEntry.Types.EntryEntry> internal__static_protobuf_unittest_MessageContainingMapCalledEntry_EntryEntry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestMap__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestMap_MapInt32Int32Entry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestMap_MapInt64Int64Entry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestMap_MapUint32Uint32Entry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestMap_MapUint64Uint64Entry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestMap_MapSint32Sint32Entry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestMap_MapSint64Sint64Entry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestMap_MapFixed32Fixed32Entry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestMap_MapFixed64Fixed64Entry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestMap_MapSfixed32Sfixed32Entry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestMap_MapSfixed64Sfixed64Entry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestMap_MapInt32FloatEntry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestMap_MapInt32DoubleEntry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestMap_MapBoolBoolEntry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestMap_MapStringStringEntry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestMap_MapInt32BytesEntry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestMap_MapInt32EnumEntry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestMap_MapInt32ForeignMessageEntry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestMapSubmessage__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestMessageMap__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestMessageMap_MapInt32MessageEntry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestSameTypeMap__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestSameTypeMap_Map1Entry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestSameTypeMap_Map2Entry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestArenaMap__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestArenaMap_MapInt32Int32Entry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestArenaMap_MapInt64Int64Entry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestArenaMap_MapUint32Uint32Entry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestArenaMap_MapUint64Uint64Entry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestArenaMap_MapSint32Sint32Entry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestArenaMap_MapSint64Sint64Entry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestArenaMap_MapFixed32Fixed32Entry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestArenaMap_MapFixed64Fixed64Entry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestArenaMap_MapSfixed32Sfixed32Entry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestArenaMap_MapSfixed64Sfixed64Entry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestArenaMap_MapInt32FloatEntry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestArenaMap_MapInt32DoubleEntry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestArenaMap_MapBoolBoolEntry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestArenaMap_MapInt32EnumEntry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestArenaMap_MapInt32ForeignMessageEntry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_MessageContainingEnumCalledType__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_MessageContainingEnumCalledType_TypeEntry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_MessageContainingMapCalledEntry__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_MessageContainingMapCalledEntry_EntryEntry__FieldAccessorTable;
     #endregion
     #region Descriptor
     public static pbd::FileDescriptor Descriptor {
@@ -235,189 +191,142 @@
             "dmFsdWUYAiABKAU6AjgBKj8KB01hcEVudW0SEAoMTUFQX0VOVU1fRk9PEAAS", 
             "EAoMTUFQX0VOVU1fQkFSEAESEAoMTUFQX0VOVU1fQkFaEAJCIPgBAaoCGkdv", 
           "b2dsZS5Qcm90b2J1Zi5UZXN0UHJvdG9zYgZwcm90bzM="));
-      pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {
-        descriptor = root;
-        internal__static_protobuf_unittest_TestMap__Descriptor = Descriptor.MessageTypes[0];
-        internal__static_protobuf_unittest_TestMap__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap>(internal__static_protobuf_unittest_TestMap__Descriptor,
-                new string[] { "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapStringString", "MapInt32Bytes", "MapInt32Enum", "MapInt32ForeignMessage", });
-        internal__static_protobuf_unittest_TestMap_MapInt32Int32Entry__Descriptor = internal__static_protobuf_unittest_TestMap__Descriptor.NestedTypes[0];
-        internal__static_protobuf_unittest_TestMap_MapInt32Int32Entry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapInt32Int32Entry>(internal__static_protobuf_unittest_TestMap_MapInt32Int32Entry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_TestMap_MapInt64Int64Entry__Descriptor = internal__static_protobuf_unittest_TestMap__Descriptor.NestedTypes[1];
-        internal__static_protobuf_unittest_TestMap_MapInt64Int64Entry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapInt64Int64Entry>(internal__static_protobuf_unittest_TestMap_MapInt64Int64Entry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_TestMap_MapUint32Uint32Entry__Descriptor = internal__static_protobuf_unittest_TestMap__Descriptor.NestedTypes[2];
-        internal__static_protobuf_unittest_TestMap_MapUint32Uint32Entry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapUint32Uint32Entry>(internal__static_protobuf_unittest_TestMap_MapUint32Uint32Entry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_TestMap_MapUint64Uint64Entry__Descriptor = internal__static_protobuf_unittest_TestMap__Descriptor.NestedTypes[3];
-        internal__static_protobuf_unittest_TestMap_MapUint64Uint64Entry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapUint64Uint64Entry>(internal__static_protobuf_unittest_TestMap_MapUint64Uint64Entry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_TestMap_MapSint32Sint32Entry__Descriptor = internal__static_protobuf_unittest_TestMap__Descriptor.NestedTypes[4];
-        internal__static_protobuf_unittest_TestMap_MapSint32Sint32Entry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapSint32Sint32Entry>(internal__static_protobuf_unittest_TestMap_MapSint32Sint32Entry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_TestMap_MapSint64Sint64Entry__Descriptor = internal__static_protobuf_unittest_TestMap__Descriptor.NestedTypes[5];
-        internal__static_protobuf_unittest_TestMap_MapSint64Sint64Entry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapSint64Sint64Entry>(internal__static_protobuf_unittest_TestMap_MapSint64Sint64Entry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_TestMap_MapFixed32Fixed32Entry__Descriptor = internal__static_protobuf_unittest_TestMap__Descriptor.NestedTypes[6];
-        internal__static_protobuf_unittest_TestMap_MapFixed32Fixed32Entry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapFixed32Fixed32Entry>(internal__static_protobuf_unittest_TestMap_MapFixed32Fixed32Entry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_TestMap_MapFixed64Fixed64Entry__Descriptor = internal__static_protobuf_unittest_TestMap__Descriptor.NestedTypes[7];
-        internal__static_protobuf_unittest_TestMap_MapFixed64Fixed64Entry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapFixed64Fixed64Entry>(internal__static_protobuf_unittest_TestMap_MapFixed64Fixed64Entry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_TestMap_MapSfixed32Sfixed32Entry__Descriptor = internal__static_protobuf_unittest_TestMap__Descriptor.NestedTypes[8];
-        internal__static_protobuf_unittest_TestMap_MapSfixed32Sfixed32Entry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapSfixed32Sfixed32Entry>(internal__static_protobuf_unittest_TestMap_MapSfixed32Sfixed32Entry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_TestMap_MapSfixed64Sfixed64Entry__Descriptor = internal__static_protobuf_unittest_TestMap__Descriptor.NestedTypes[9];
-        internal__static_protobuf_unittest_TestMap_MapSfixed64Sfixed64Entry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapSfixed64Sfixed64Entry>(internal__static_protobuf_unittest_TestMap_MapSfixed64Sfixed64Entry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_TestMap_MapInt32FloatEntry__Descriptor = internal__static_protobuf_unittest_TestMap__Descriptor.NestedTypes[10];
-        internal__static_protobuf_unittest_TestMap_MapInt32FloatEntry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapInt32FloatEntry>(internal__static_protobuf_unittest_TestMap_MapInt32FloatEntry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_TestMap_MapInt32DoubleEntry__Descriptor = internal__static_protobuf_unittest_TestMap__Descriptor.NestedTypes[11];
-        internal__static_protobuf_unittest_TestMap_MapInt32DoubleEntry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapInt32DoubleEntry>(internal__static_protobuf_unittest_TestMap_MapInt32DoubleEntry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_TestMap_MapBoolBoolEntry__Descriptor = internal__static_protobuf_unittest_TestMap__Descriptor.NestedTypes[12];
-        internal__static_protobuf_unittest_TestMap_MapBoolBoolEntry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapBoolBoolEntry>(internal__static_protobuf_unittest_TestMap_MapBoolBoolEntry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_TestMap_MapStringStringEntry__Descriptor = internal__static_protobuf_unittest_TestMap__Descriptor.NestedTypes[13];
-        internal__static_protobuf_unittest_TestMap_MapStringStringEntry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapStringStringEntry>(internal__static_protobuf_unittest_TestMap_MapStringStringEntry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_TestMap_MapInt32BytesEntry__Descriptor = internal__static_protobuf_unittest_TestMap__Descriptor.NestedTypes[14];
-        internal__static_protobuf_unittest_TestMap_MapInt32BytesEntry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapInt32BytesEntry>(internal__static_protobuf_unittest_TestMap_MapInt32BytesEntry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_TestMap_MapInt32EnumEntry__Descriptor = internal__static_protobuf_unittest_TestMap__Descriptor.NestedTypes[15];
-        internal__static_protobuf_unittest_TestMap_MapInt32EnumEntry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapInt32EnumEntry>(internal__static_protobuf_unittest_TestMap_MapInt32EnumEntry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_TestMap_MapInt32ForeignMessageEntry__Descriptor = internal__static_protobuf_unittest_TestMap__Descriptor.NestedTypes[16];
-        internal__static_protobuf_unittest_TestMap_MapInt32ForeignMessageEntry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapInt32ForeignMessageEntry>(internal__static_protobuf_unittest_TestMap_MapInt32ForeignMessageEntry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_TestMapSubmessage__Descriptor = Descriptor.MessageTypes[1];
-        internal__static_protobuf_unittest_TestMapSubmessage__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMapSubmessage>(internal__static_protobuf_unittest_TestMapSubmessage__Descriptor,
-                new string[] { "TestMap", });
-        internal__static_protobuf_unittest_TestMessageMap__Descriptor = Descriptor.MessageTypes[2];
-        internal__static_protobuf_unittest_TestMessageMap__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMessageMap>(internal__static_protobuf_unittest_TestMessageMap__Descriptor,
-                new string[] { "MapInt32Message", });
-        internal__static_protobuf_unittest_TestMessageMap_MapInt32MessageEntry__Descriptor = internal__static_protobuf_unittest_TestMessageMap__Descriptor.NestedTypes[0];
-        internal__static_protobuf_unittest_TestMessageMap_MapInt32MessageEntry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMessageMap.Types.MapInt32MessageEntry>(internal__static_protobuf_unittest_TestMessageMap_MapInt32MessageEntry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_TestSameTypeMap__Descriptor = Descriptor.MessageTypes[3];
-        internal__static_protobuf_unittest_TestSameTypeMap__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestSameTypeMap>(internal__static_protobuf_unittest_TestSameTypeMap__Descriptor,
-                new string[] { "Map1", "Map2", });
-        internal__static_protobuf_unittest_TestSameTypeMap_Map1Entry__Descriptor = internal__static_protobuf_unittest_TestSameTypeMap__Descriptor.NestedTypes[0];
-        internal__static_protobuf_unittest_TestSameTypeMap_Map1Entry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestSameTypeMap.Types.Map1Entry>(internal__static_protobuf_unittest_TestSameTypeMap_Map1Entry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_TestSameTypeMap_Map2Entry__Descriptor = internal__static_protobuf_unittest_TestSameTypeMap__Descriptor.NestedTypes[1];
-        internal__static_protobuf_unittest_TestSameTypeMap_Map2Entry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestSameTypeMap.Types.Map2Entry>(internal__static_protobuf_unittest_TestSameTypeMap_Map2Entry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_TestArenaMap__Descriptor = Descriptor.MessageTypes[4];
-        internal__static_protobuf_unittest_TestArenaMap__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap>(internal__static_protobuf_unittest_TestArenaMap__Descriptor,
-                new string[] { "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapInt32Enum", "MapInt32ForeignMessage", });
-        internal__static_protobuf_unittest_TestArenaMap_MapInt32Int32Entry__Descriptor = internal__static_protobuf_unittest_TestArenaMap__Descriptor.NestedTypes[0];
-        internal__static_protobuf_unittest_TestArenaMap_MapInt32Int32Entry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapInt32Int32Entry>(internal__static_protobuf_unittest_TestArenaMap_MapInt32Int32Entry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_TestArenaMap_MapInt64Int64Entry__Descriptor = internal__static_protobuf_unittest_TestArenaMap__Descriptor.NestedTypes[1];
-        internal__static_protobuf_unittest_TestArenaMap_MapInt64Int64Entry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapInt64Int64Entry>(internal__static_protobuf_unittest_TestArenaMap_MapInt64Int64Entry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_TestArenaMap_MapUint32Uint32Entry__Descriptor = internal__static_protobuf_unittest_TestArenaMap__Descriptor.NestedTypes[2];
-        internal__static_protobuf_unittest_TestArenaMap_MapUint32Uint32Entry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapUint32Uint32Entry>(internal__static_protobuf_unittest_TestArenaMap_MapUint32Uint32Entry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_TestArenaMap_MapUint64Uint64Entry__Descriptor = internal__static_protobuf_unittest_TestArenaMap__Descriptor.NestedTypes[3];
-        internal__static_protobuf_unittest_TestArenaMap_MapUint64Uint64Entry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapUint64Uint64Entry>(internal__static_protobuf_unittest_TestArenaMap_MapUint64Uint64Entry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_TestArenaMap_MapSint32Sint32Entry__Descriptor = internal__static_protobuf_unittest_TestArenaMap__Descriptor.NestedTypes[4];
-        internal__static_protobuf_unittest_TestArenaMap_MapSint32Sint32Entry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapSint32Sint32Entry>(internal__static_protobuf_unittest_TestArenaMap_MapSint32Sint32Entry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_TestArenaMap_MapSint64Sint64Entry__Descriptor = internal__static_protobuf_unittest_TestArenaMap__Descriptor.NestedTypes[5];
-        internal__static_protobuf_unittest_TestArenaMap_MapSint64Sint64Entry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapSint64Sint64Entry>(internal__static_protobuf_unittest_TestArenaMap_MapSint64Sint64Entry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_TestArenaMap_MapFixed32Fixed32Entry__Descriptor = internal__static_protobuf_unittest_TestArenaMap__Descriptor.NestedTypes[6];
-        internal__static_protobuf_unittest_TestArenaMap_MapFixed32Fixed32Entry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapFixed32Fixed32Entry>(internal__static_protobuf_unittest_TestArenaMap_MapFixed32Fixed32Entry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_TestArenaMap_MapFixed64Fixed64Entry__Descriptor = internal__static_protobuf_unittest_TestArenaMap__Descriptor.NestedTypes[7];
-        internal__static_protobuf_unittest_TestArenaMap_MapFixed64Fixed64Entry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapFixed64Fixed64Entry>(internal__static_protobuf_unittest_TestArenaMap_MapFixed64Fixed64Entry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_TestArenaMap_MapSfixed32Sfixed32Entry__Descriptor = internal__static_protobuf_unittest_TestArenaMap__Descriptor.NestedTypes[8];
-        internal__static_protobuf_unittest_TestArenaMap_MapSfixed32Sfixed32Entry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapSfixed32Sfixed32Entry>(internal__static_protobuf_unittest_TestArenaMap_MapSfixed32Sfixed32Entry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_TestArenaMap_MapSfixed64Sfixed64Entry__Descriptor = internal__static_protobuf_unittest_TestArenaMap__Descriptor.NestedTypes[9];
-        internal__static_protobuf_unittest_TestArenaMap_MapSfixed64Sfixed64Entry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapSfixed64Sfixed64Entry>(internal__static_protobuf_unittest_TestArenaMap_MapSfixed64Sfixed64Entry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_TestArenaMap_MapInt32FloatEntry__Descriptor = internal__static_protobuf_unittest_TestArenaMap__Descriptor.NestedTypes[10];
-        internal__static_protobuf_unittest_TestArenaMap_MapInt32FloatEntry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapInt32FloatEntry>(internal__static_protobuf_unittest_TestArenaMap_MapInt32FloatEntry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_TestArenaMap_MapInt32DoubleEntry__Descriptor = internal__static_protobuf_unittest_TestArenaMap__Descriptor.NestedTypes[11];
-        internal__static_protobuf_unittest_TestArenaMap_MapInt32DoubleEntry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapInt32DoubleEntry>(internal__static_protobuf_unittest_TestArenaMap_MapInt32DoubleEntry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_TestArenaMap_MapBoolBoolEntry__Descriptor = internal__static_protobuf_unittest_TestArenaMap__Descriptor.NestedTypes[12];
-        internal__static_protobuf_unittest_TestArenaMap_MapBoolBoolEntry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapBoolBoolEntry>(internal__static_protobuf_unittest_TestArenaMap_MapBoolBoolEntry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_TestArenaMap_MapInt32EnumEntry__Descriptor = internal__static_protobuf_unittest_TestArenaMap__Descriptor.NestedTypes[13];
-        internal__static_protobuf_unittest_TestArenaMap_MapInt32EnumEntry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapInt32EnumEntry>(internal__static_protobuf_unittest_TestArenaMap_MapInt32EnumEntry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_TestArenaMap_MapInt32ForeignMessageEntry__Descriptor = internal__static_protobuf_unittest_TestArenaMap__Descriptor.NestedTypes[14];
-        internal__static_protobuf_unittest_TestArenaMap_MapInt32ForeignMessageEntry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapInt32ForeignMessageEntry>(internal__static_protobuf_unittest_TestArenaMap_MapInt32ForeignMessageEntry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_MessageContainingEnumCalledType__Descriptor = Descriptor.MessageTypes[5];
-        internal__static_protobuf_unittest_MessageContainingEnumCalledType__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType>(internal__static_protobuf_unittest_MessageContainingEnumCalledType__Descriptor,
-                new string[] { "Type", });
-        internal__static_protobuf_unittest_MessageContainingEnumCalledType_TypeEntry__Descriptor = internal__static_protobuf_unittest_MessageContainingEnumCalledType__Descriptor.NestedTypes[0];
-        internal__static_protobuf_unittest_MessageContainingEnumCalledType_TypeEntry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType.Types.TypeEntry>(internal__static_protobuf_unittest_MessageContainingEnumCalledType_TypeEntry__Descriptor,
-                new string[] { "Key", "Value", });
-        internal__static_protobuf_unittest_MessageContainingMapCalledEntry__Descriptor = Descriptor.MessageTypes[6];
-        internal__static_protobuf_unittest_MessageContainingMapCalledEntry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.MessageContainingMapCalledEntry>(internal__static_protobuf_unittest_MessageContainingMapCalledEntry__Descriptor,
-                new string[] { "Entry", });
-        internal__static_protobuf_unittest_MessageContainingMapCalledEntry_EntryEntry__Descriptor = internal__static_protobuf_unittest_MessageContainingMapCalledEntry__Descriptor.NestedTypes[0];
-        internal__static_protobuf_unittest_MessageContainingMapCalledEntry_EntryEntry__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.MessageContainingMapCalledEntry.Types.EntryEntry>(internal__static_protobuf_unittest_MessageContainingMapCalledEntry_EntryEntry__Descriptor,
-                new string[] { "Key", "Value", });
-      };
-      pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
+      descriptor = pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
           new pbd::FileDescriptor[] {
           global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor, 
-          }, assigner);
+          });
+      internal__static_protobuf_unittest_TestMap__FieldAccessorTable = 
+          new pb::FieldAccess.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", });
+      internal__static_protobuf_unittest_TestMap_MapInt32Int32Entry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestMap.Types.MapInt32Int32Entry), descriptor.MessageTypes[0].NestedTypes[0],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_TestMap_MapInt64Int64Entry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestMap.Types.MapInt64Int64Entry), descriptor.MessageTypes[0].NestedTypes[1],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_TestMap_MapUint32Uint32Entry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestMap.Types.MapUint32Uint32Entry), descriptor.MessageTypes[0].NestedTypes[2],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_TestMap_MapUint64Uint64Entry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestMap.Types.MapUint64Uint64Entry), descriptor.MessageTypes[0].NestedTypes[3],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_TestMap_MapSint32Sint32Entry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestMap.Types.MapSint32Sint32Entry), descriptor.MessageTypes[0].NestedTypes[4],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_TestMap_MapSint64Sint64Entry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestMap.Types.MapSint64Sint64Entry), descriptor.MessageTypes[0].NestedTypes[5],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_TestMap_MapFixed32Fixed32Entry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestMap.Types.MapFixed32Fixed32Entry), descriptor.MessageTypes[0].NestedTypes[6],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_TestMap_MapFixed64Fixed64Entry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestMap.Types.MapFixed64Fixed64Entry), descriptor.MessageTypes[0].NestedTypes[7],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_TestMap_MapSfixed32Sfixed32Entry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestMap.Types.MapSfixed32Sfixed32Entry), descriptor.MessageTypes[0].NestedTypes[8],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_TestMap_MapSfixed64Sfixed64Entry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestMap.Types.MapSfixed64Sfixed64Entry), descriptor.MessageTypes[0].NestedTypes[9],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_TestMap_MapInt32FloatEntry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestMap.Types.MapInt32FloatEntry), descriptor.MessageTypes[0].NestedTypes[10],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_TestMap_MapInt32DoubleEntry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestMap.Types.MapInt32DoubleEntry), descriptor.MessageTypes[0].NestedTypes[11],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_TestMap_MapBoolBoolEntry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestMap.Types.MapBoolBoolEntry), descriptor.MessageTypes[0].NestedTypes[12],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_TestMap_MapStringStringEntry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestMap.Types.MapStringStringEntry), descriptor.MessageTypes[0].NestedTypes[13],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_TestMap_MapInt32BytesEntry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestMap.Types.MapInt32BytesEntry), descriptor.MessageTypes[0].NestedTypes[14],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_TestMap_MapInt32EnumEntry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestMap.Types.MapInt32EnumEntry), descriptor.MessageTypes[0].NestedTypes[15],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_TestMap_MapInt32ForeignMessageEntry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestMap.Types.MapInt32ForeignMessageEntry), descriptor.MessageTypes[0].NestedTypes[16],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_TestMapSubmessage__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestMapSubmessage), descriptor.MessageTypes[1],
+              new string[] { "TestMap", });
+      internal__static_protobuf_unittest_TestMessageMap__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestMessageMap), descriptor.MessageTypes[2],
+              new string[] { "MapInt32Message", });
+      internal__static_protobuf_unittest_TestMessageMap_MapInt32MessageEntry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestMessageMap.Types.MapInt32MessageEntry), descriptor.MessageTypes[2].NestedTypes[0],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_TestSameTypeMap__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestSameTypeMap), descriptor.MessageTypes[3],
+              new string[] { "Map1", "Map2", });
+      internal__static_protobuf_unittest_TestSameTypeMap_Map1Entry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestSameTypeMap.Types.Map1Entry), descriptor.MessageTypes[3].NestedTypes[0],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_TestSameTypeMap_Map2Entry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestSameTypeMap.Types.Map2Entry), descriptor.MessageTypes[3].NestedTypes[1],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_TestArenaMap__FieldAccessorTable = 
+          new pb::FieldAccess.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", });
+      internal__static_protobuf_unittest_TestArenaMap_MapInt32Int32Entry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapInt32Int32Entry), descriptor.MessageTypes[4].NestedTypes[0],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_TestArenaMap_MapInt64Int64Entry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapInt64Int64Entry), descriptor.MessageTypes[4].NestedTypes[1],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_TestArenaMap_MapUint32Uint32Entry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapUint32Uint32Entry), descriptor.MessageTypes[4].NestedTypes[2],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_TestArenaMap_MapUint64Uint64Entry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapUint64Uint64Entry), descriptor.MessageTypes[4].NestedTypes[3],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_TestArenaMap_MapSint32Sint32Entry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapSint32Sint32Entry), descriptor.MessageTypes[4].NestedTypes[4],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_TestArenaMap_MapSint64Sint64Entry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapSint64Sint64Entry), descriptor.MessageTypes[4].NestedTypes[5],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_TestArenaMap_MapFixed32Fixed32Entry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapFixed32Fixed32Entry), descriptor.MessageTypes[4].NestedTypes[6],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_TestArenaMap_MapFixed64Fixed64Entry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapFixed64Fixed64Entry), descriptor.MessageTypes[4].NestedTypes[7],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_TestArenaMap_MapSfixed32Sfixed32Entry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapSfixed32Sfixed32Entry), descriptor.MessageTypes[4].NestedTypes[8],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_TestArenaMap_MapSfixed64Sfixed64Entry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapSfixed64Sfixed64Entry), descriptor.MessageTypes[4].NestedTypes[9],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_TestArenaMap_MapInt32FloatEntry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapInt32FloatEntry), descriptor.MessageTypes[4].NestedTypes[10],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_TestArenaMap_MapInt32DoubleEntry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapInt32DoubleEntry), descriptor.MessageTypes[4].NestedTypes[11],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_TestArenaMap_MapBoolBoolEntry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapBoolBoolEntry), descriptor.MessageTypes[4].NestedTypes[12],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_TestArenaMap_MapInt32EnumEntry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapInt32EnumEntry), descriptor.MessageTypes[4].NestedTypes[13],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_TestArenaMap_MapInt32ForeignMessageEntry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapInt32ForeignMessageEntry), descriptor.MessageTypes[4].NestedTypes[14],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_MessageContainingEnumCalledType__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType), descriptor.MessageTypes[5],
+              new string[] { "Type", });
+      internal__static_protobuf_unittest_MessageContainingEnumCalledType_TypeEntry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType.Types.TypeEntry), descriptor.MessageTypes[5].NestedTypes[0],
+              new string[] { "Key", "Value", });
+      internal__static_protobuf_unittest_MessageContainingMapCalledEntry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.MessageContainingMapCalledEntry), descriptor.MessageTypes[6],
+              new string[] { "Entry", });
+      internal__static_protobuf_unittest_MessageContainingMapCalledEntry_EntryEntry__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.MessageContainingMapCalledEntry.Types.EntryEntry), descriptor.MessageTypes[6].NestedTypes[0],
+              new string[] { "Key", "Value", });
     }
     #endregion
 
@@ -440,19 +349,23 @@
     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 pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.Descriptor.MessageTypes[0]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<TestMap> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public TestMap() { }
+    public TestMap() {
+      OnConstruction();
+    }
 
-    public TestMap(TestMap other) {
+    partial void OnConstruction();
+
+    public TestMap(TestMap other) : this() {
       mapInt32Int32_ = other.mapInt32Int32_.Clone();
       mapInt64Int64_ = other.mapInt64Int64_.Clone();
       mapUint32Uint32_ = other.mapUint32Uint32_.Clone();
@@ -848,19 +761,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapInt32Int32Entry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestMap.Descriptor.NestedTypes[0]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<MapInt32Int32Entry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapInt32Int32Entry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public MapInt32Int32Entry() { }
+        public MapInt32Int32Entry() {
+          OnConstruction();
+        }
 
-        public MapInt32Int32Entry(MapInt32Int32Entry other) {
+        partial void OnConstruction();
+
+        public MapInt32Int32Entry(MapInt32Int32Entry other) : this() {
           key_ = other.key_;
           value_ = other.value_;
         }
@@ -986,19 +903,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapInt64Int64Entry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestMap.Descriptor.NestedTypes[1]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<MapInt64Int64Entry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapInt64Int64Entry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public MapInt64Int64Entry() { }
+        public MapInt64Int64Entry() {
+          OnConstruction();
+        }
 
-        public MapInt64Int64Entry(MapInt64Int64Entry other) {
+        partial void OnConstruction();
+
+        public MapInt64Int64Entry(MapInt64Int64Entry other) : this() {
           key_ = other.key_;
           value_ = other.value_;
         }
@@ -1124,19 +1045,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapUint32Uint32Entry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestMap.Descriptor.NestedTypes[2]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<MapUint32Uint32Entry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapUint32Uint32Entry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public MapUint32Uint32Entry() { }
+        public MapUint32Uint32Entry() {
+          OnConstruction();
+        }
 
-        public MapUint32Uint32Entry(MapUint32Uint32Entry other) {
+        partial void OnConstruction();
+
+        public MapUint32Uint32Entry(MapUint32Uint32Entry other) : this() {
           key_ = other.key_;
           value_ = other.value_;
         }
@@ -1262,19 +1187,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapUint64Uint64Entry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestMap.Descriptor.NestedTypes[3]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<MapUint64Uint64Entry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapUint64Uint64Entry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public MapUint64Uint64Entry() { }
+        public MapUint64Uint64Entry() {
+          OnConstruction();
+        }
 
-        public MapUint64Uint64Entry(MapUint64Uint64Entry other) {
+        partial void OnConstruction();
+
+        public MapUint64Uint64Entry(MapUint64Uint64Entry other) : this() {
           key_ = other.key_;
           value_ = other.value_;
         }
@@ -1400,19 +1329,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapSint32Sint32Entry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestMap.Descriptor.NestedTypes[4]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<MapSint32Sint32Entry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapSint32Sint32Entry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public MapSint32Sint32Entry() { }
+        public MapSint32Sint32Entry() {
+          OnConstruction();
+        }
 
-        public MapSint32Sint32Entry(MapSint32Sint32Entry other) {
+        partial void OnConstruction();
+
+        public MapSint32Sint32Entry(MapSint32Sint32Entry other) : this() {
           key_ = other.key_;
           value_ = other.value_;
         }
@@ -1538,19 +1471,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapSint64Sint64Entry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestMap.Descriptor.NestedTypes[5]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<MapSint64Sint64Entry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapSint64Sint64Entry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public MapSint64Sint64Entry() { }
+        public MapSint64Sint64Entry() {
+          OnConstruction();
+        }
 
-        public MapSint64Sint64Entry(MapSint64Sint64Entry other) {
+        partial void OnConstruction();
+
+        public MapSint64Sint64Entry(MapSint64Sint64Entry other) : this() {
           key_ = other.key_;
           value_ = other.value_;
         }
@@ -1676,19 +1613,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 13, 21 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapFixed32Fixed32Entry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestMap.Descriptor.NestedTypes[6]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<MapFixed32Fixed32Entry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapFixed32Fixed32Entry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public MapFixed32Fixed32Entry() { }
+        public MapFixed32Fixed32Entry() {
+          OnConstruction();
+        }
 
-        public MapFixed32Fixed32Entry(MapFixed32Fixed32Entry other) {
+        partial void OnConstruction();
+
+        public MapFixed32Fixed32Entry(MapFixed32Fixed32Entry other) : this() {
           key_ = other.key_;
           value_ = other.value_;
         }
@@ -1814,19 +1755,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 9, 17 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapFixed64Fixed64Entry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestMap.Descriptor.NestedTypes[7]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<MapFixed64Fixed64Entry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapFixed64Fixed64Entry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public MapFixed64Fixed64Entry() { }
+        public MapFixed64Fixed64Entry() {
+          OnConstruction();
+        }
 
-        public MapFixed64Fixed64Entry(MapFixed64Fixed64Entry other) {
+        partial void OnConstruction();
+
+        public MapFixed64Fixed64Entry(MapFixed64Fixed64Entry other) : this() {
           key_ = other.key_;
           value_ = other.value_;
         }
@@ -1952,19 +1897,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 13, 21 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapSfixed32Sfixed32Entry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestMap.Descriptor.NestedTypes[8]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<MapSfixed32Sfixed32Entry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapSfixed32Sfixed32Entry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public MapSfixed32Sfixed32Entry() { }
+        public MapSfixed32Sfixed32Entry() {
+          OnConstruction();
+        }
 
-        public MapSfixed32Sfixed32Entry(MapSfixed32Sfixed32Entry other) {
+        partial void OnConstruction();
+
+        public MapSfixed32Sfixed32Entry(MapSfixed32Sfixed32Entry other) : this() {
           key_ = other.key_;
           value_ = other.value_;
         }
@@ -2090,19 +2039,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 9, 17 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapSfixed64Sfixed64Entry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestMap.Descriptor.NestedTypes[9]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<MapSfixed64Sfixed64Entry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapSfixed64Sfixed64Entry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public MapSfixed64Sfixed64Entry() { }
+        public MapSfixed64Sfixed64Entry() {
+          OnConstruction();
+        }
 
-        public MapSfixed64Sfixed64Entry(MapSfixed64Sfixed64Entry other) {
+        partial void OnConstruction();
+
+        public MapSfixed64Sfixed64Entry(MapSfixed64Sfixed64Entry other) : this() {
           key_ = other.key_;
           value_ = other.value_;
         }
@@ -2228,19 +2181,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 8, 21 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapInt32FloatEntry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestMap.Descriptor.NestedTypes[10]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<MapInt32FloatEntry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapInt32FloatEntry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public MapInt32FloatEntry() { }
+        public MapInt32FloatEntry() {
+          OnConstruction();
+        }
 
-        public MapInt32FloatEntry(MapInt32FloatEntry other) {
+        partial void OnConstruction();
+
+        public MapInt32FloatEntry(MapInt32FloatEntry other) : this() {
           key_ = other.key_;
           value_ = other.value_;
         }
@@ -2366,19 +2323,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 8, 17 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapInt32DoubleEntry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestMap.Descriptor.NestedTypes[11]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<MapInt32DoubleEntry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapInt32DoubleEntry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public MapInt32DoubleEntry() { }
+        public MapInt32DoubleEntry() {
+          OnConstruction();
+        }
 
-        public MapInt32DoubleEntry(MapInt32DoubleEntry other) {
+        partial void OnConstruction();
+
+        public MapInt32DoubleEntry(MapInt32DoubleEntry other) : this() {
           key_ = other.key_;
           value_ = other.value_;
         }
@@ -2504,19 +2465,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapBoolBoolEntry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestMap.Descriptor.NestedTypes[12]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<MapBoolBoolEntry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapBoolBoolEntry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public MapBoolBoolEntry() { }
+        public MapBoolBoolEntry() {
+          OnConstruction();
+        }
 
-        public MapBoolBoolEntry(MapBoolBoolEntry other) {
+        partial void OnConstruction();
+
+        public MapBoolBoolEntry(MapBoolBoolEntry other) : this() {
           key_ = other.key_;
           value_ = other.value_;
         }
@@ -2642,19 +2607,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 10, 18 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapStringStringEntry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestMap.Descriptor.NestedTypes[13]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<MapStringStringEntry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapStringStringEntry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public MapStringStringEntry() { }
+        public MapStringStringEntry() {
+          OnConstruction();
+        }
 
-        public MapStringStringEntry(MapStringStringEntry other) {
+        partial void OnConstruction();
+
+        public MapStringStringEntry(MapStringStringEntry other) : this() {
           key_ = other.key_;
           value_ = other.value_;
         }
@@ -2780,19 +2749,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 8, 18 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapInt32BytesEntry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestMap.Descriptor.NestedTypes[14]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<MapInt32BytesEntry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapInt32BytesEntry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public MapInt32BytesEntry() { }
+        public MapInt32BytesEntry() {
+          OnConstruction();
+        }
 
-        public MapInt32BytesEntry(MapInt32BytesEntry other) {
+        partial void OnConstruction();
+
+        public MapInt32BytesEntry(MapInt32BytesEntry other) : this() {
           key_ = other.key_;
           value_ = other.value_;
         }
@@ -2918,19 +2891,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapInt32EnumEntry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestMap.Descriptor.NestedTypes[15]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<MapInt32EnumEntry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapInt32EnumEntry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public MapInt32EnumEntry() { }
+        public MapInt32EnumEntry() {
+          OnConstruction();
+        }
 
-        public MapInt32EnumEntry(MapInt32EnumEntry other) {
+        partial void OnConstruction();
+
+        public MapInt32EnumEntry(MapInt32EnumEntry other) : this() {
           key_ = other.key_;
           value_ = other.value_;
         }
@@ -3056,19 +3033,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 8, 18 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapInt32ForeignMessageEntry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestMap.Descriptor.NestedTypes[16]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<MapInt32ForeignMessageEntry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapInt32ForeignMessageEntry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public MapInt32ForeignMessageEntry() { }
+        public MapInt32ForeignMessageEntry() {
+          OnConstruction();
+        }
 
-        public MapInt32ForeignMessageEntry(MapInt32ForeignMessageEntry other) {
+        partial void OnConstruction();
+
+        public MapInt32ForeignMessageEntry(MapInt32ForeignMessageEntry other) : this() {
           key_ = other.key_;
           Value = other.value_ != null ? other.Value.Clone() : null;
         }
@@ -3206,19 +3187,23 @@
     private static readonly string[] _fieldNames = new string[] { "test_map" };
     private static readonly uint[] _fieldTags = new uint[] { 10 };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMapSubmessage__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.Descriptor.MessageTypes[1]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<TestMapSubmessage> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMapSubmessage__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public TestMapSubmessage() { }
+    public TestMapSubmessage() {
+      OnConstruction();
+    }
 
-    public TestMapSubmessage(TestMapSubmessage other) {
+    partial void OnConstruction();
+
+    public TestMapSubmessage(TestMapSubmessage other) : this() {
       TestMap = other.testMap_ != null ? other.TestMap.Clone() : null;
     }
 
@@ -3324,19 +3309,23 @@
     private static readonly string[] _fieldNames = new string[] { "map_int32_message" };
     private static readonly uint[] _fieldTags = new uint[] { 10 };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMessageMap__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.Descriptor.MessageTypes[2]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<TestMessageMap> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMessageMap__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public TestMessageMap() { }
+    public TestMessageMap() {
+      OnConstruction();
+    }
 
-    public TestMessageMap(TestMessageMap other) {
+    partial void OnConstruction();
+
+    public TestMessageMap(TestMessageMap other) : this() {
       mapInt32Message_ = other.mapInt32Message_.Clone();
     }
 
@@ -3428,19 +3417,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 8, 18 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMessageMap_MapInt32MessageEntry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestMessageMap.Descriptor.NestedTypes[0]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<MapInt32MessageEntry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMessageMap_MapInt32MessageEntry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public MapInt32MessageEntry() { }
+        public MapInt32MessageEntry() {
+          OnConstruction();
+        }
 
-        public MapInt32MessageEntry(MapInt32MessageEntry other) {
+        partial void OnConstruction();
+
+        public MapInt32MessageEntry(MapInt32MessageEntry other) : this() {
           key_ = other.key_;
           Value = other.value_ != null ? other.Value.Clone() : null;
         }
@@ -3578,19 +3571,23 @@
     private static readonly string[] _fieldNames = new string[] { "map1", "map2" };
     private static readonly uint[] _fieldTags = new uint[] { 10, 18 };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestSameTypeMap__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.Descriptor.MessageTypes[3]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<TestSameTypeMap> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestSameTypeMap__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public TestSameTypeMap() { }
+    public TestSameTypeMap() {
+      OnConstruction();
+    }
 
-    public TestSameTypeMap(TestSameTypeMap other) {
+    partial void OnConstruction();
+
+    public TestSameTypeMap(TestSameTypeMap other) : this() {
       map1_ = other.map1_.Clone();
       map2_ = other.map2_.Clone();
     }
@@ -3701,19 +3698,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestSameTypeMap_Map1Entry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestSameTypeMap.Descriptor.NestedTypes[0]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<Map1Entry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestSameTypeMap_Map1Entry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public Map1Entry() { }
+        public Map1Entry() {
+          OnConstruction();
+        }
 
-        public Map1Entry(Map1Entry other) {
+        partial void OnConstruction();
+
+        public Map1Entry(Map1Entry other) : this() {
           key_ = other.key_;
           value_ = other.value_;
         }
@@ -3839,19 +3840,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestSameTypeMap_Map2Entry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestSameTypeMap.Descriptor.NestedTypes[1]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<Map2Entry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestSameTypeMap_Map2Entry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public Map2Entry() { }
+        public Map2Entry() {
+          OnConstruction();
+        }
 
-        public Map2Entry(Map2Entry other) {
+        partial void OnConstruction();
+
+        public Map2Entry(Map2Entry other) : this() {
           key_ = other.key_;
           value_ = other.value_;
         }
@@ -3982,19 +3987,23 @@
     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 pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.Descriptor.MessageTypes[4]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<TestArenaMap> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public TestArenaMap() { }
+    public TestArenaMap() {
+      OnConstruction();
+    }
 
-    public TestArenaMap(TestArenaMap other) {
+    partial void OnConstruction();
+
+    public TestArenaMap(TestArenaMap other) : this() {
       mapInt32Int32_ = other.mapInt32Int32_.Clone();
       mapInt64Int64_ = other.mapInt64Int64_.Clone();
       mapUint32Uint32_ = other.mapUint32Uint32_.Clone();
@@ -4352,19 +4361,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapInt32Int32Entry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestArenaMap.Descriptor.NestedTypes[0]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<MapInt32Int32Entry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapInt32Int32Entry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public MapInt32Int32Entry() { }
+        public MapInt32Int32Entry() {
+          OnConstruction();
+        }
 
-        public MapInt32Int32Entry(MapInt32Int32Entry other) {
+        partial void OnConstruction();
+
+        public MapInt32Int32Entry(MapInt32Int32Entry other) : this() {
           key_ = other.key_;
           value_ = other.value_;
         }
@@ -4490,19 +4503,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapInt64Int64Entry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestArenaMap.Descriptor.NestedTypes[1]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<MapInt64Int64Entry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapInt64Int64Entry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public MapInt64Int64Entry() { }
+        public MapInt64Int64Entry() {
+          OnConstruction();
+        }
 
-        public MapInt64Int64Entry(MapInt64Int64Entry other) {
+        partial void OnConstruction();
+
+        public MapInt64Int64Entry(MapInt64Int64Entry other) : this() {
           key_ = other.key_;
           value_ = other.value_;
         }
@@ -4628,19 +4645,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapUint32Uint32Entry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestArenaMap.Descriptor.NestedTypes[2]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<MapUint32Uint32Entry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapUint32Uint32Entry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public MapUint32Uint32Entry() { }
+        public MapUint32Uint32Entry() {
+          OnConstruction();
+        }
 
-        public MapUint32Uint32Entry(MapUint32Uint32Entry other) {
+        partial void OnConstruction();
+
+        public MapUint32Uint32Entry(MapUint32Uint32Entry other) : this() {
           key_ = other.key_;
           value_ = other.value_;
         }
@@ -4766,19 +4787,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapUint64Uint64Entry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestArenaMap.Descriptor.NestedTypes[3]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<MapUint64Uint64Entry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapUint64Uint64Entry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public MapUint64Uint64Entry() { }
+        public MapUint64Uint64Entry() {
+          OnConstruction();
+        }
 
-        public MapUint64Uint64Entry(MapUint64Uint64Entry other) {
+        partial void OnConstruction();
+
+        public MapUint64Uint64Entry(MapUint64Uint64Entry other) : this() {
           key_ = other.key_;
           value_ = other.value_;
         }
@@ -4904,19 +4929,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapSint32Sint32Entry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestArenaMap.Descriptor.NestedTypes[4]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<MapSint32Sint32Entry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapSint32Sint32Entry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public MapSint32Sint32Entry() { }
+        public MapSint32Sint32Entry() {
+          OnConstruction();
+        }
 
-        public MapSint32Sint32Entry(MapSint32Sint32Entry other) {
+        partial void OnConstruction();
+
+        public MapSint32Sint32Entry(MapSint32Sint32Entry other) : this() {
           key_ = other.key_;
           value_ = other.value_;
         }
@@ -5042,19 +5071,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapSint64Sint64Entry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestArenaMap.Descriptor.NestedTypes[5]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<MapSint64Sint64Entry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapSint64Sint64Entry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public MapSint64Sint64Entry() { }
+        public MapSint64Sint64Entry() {
+          OnConstruction();
+        }
 
-        public MapSint64Sint64Entry(MapSint64Sint64Entry other) {
+        partial void OnConstruction();
+
+        public MapSint64Sint64Entry(MapSint64Sint64Entry other) : this() {
           key_ = other.key_;
           value_ = other.value_;
         }
@@ -5180,19 +5213,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 13, 21 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapFixed32Fixed32Entry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestArenaMap.Descriptor.NestedTypes[6]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<MapFixed32Fixed32Entry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapFixed32Fixed32Entry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public MapFixed32Fixed32Entry() { }
+        public MapFixed32Fixed32Entry() {
+          OnConstruction();
+        }
 
-        public MapFixed32Fixed32Entry(MapFixed32Fixed32Entry other) {
+        partial void OnConstruction();
+
+        public MapFixed32Fixed32Entry(MapFixed32Fixed32Entry other) : this() {
           key_ = other.key_;
           value_ = other.value_;
         }
@@ -5318,19 +5355,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 9, 17 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapFixed64Fixed64Entry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestArenaMap.Descriptor.NestedTypes[7]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<MapFixed64Fixed64Entry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapFixed64Fixed64Entry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public MapFixed64Fixed64Entry() { }
+        public MapFixed64Fixed64Entry() {
+          OnConstruction();
+        }
 
-        public MapFixed64Fixed64Entry(MapFixed64Fixed64Entry other) {
+        partial void OnConstruction();
+
+        public MapFixed64Fixed64Entry(MapFixed64Fixed64Entry other) : this() {
           key_ = other.key_;
           value_ = other.value_;
         }
@@ -5456,19 +5497,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 13, 21 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapSfixed32Sfixed32Entry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestArenaMap.Descriptor.NestedTypes[8]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<MapSfixed32Sfixed32Entry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapSfixed32Sfixed32Entry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public MapSfixed32Sfixed32Entry() { }
+        public MapSfixed32Sfixed32Entry() {
+          OnConstruction();
+        }
 
-        public MapSfixed32Sfixed32Entry(MapSfixed32Sfixed32Entry other) {
+        partial void OnConstruction();
+
+        public MapSfixed32Sfixed32Entry(MapSfixed32Sfixed32Entry other) : this() {
           key_ = other.key_;
           value_ = other.value_;
         }
@@ -5594,19 +5639,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 9, 17 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapSfixed64Sfixed64Entry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestArenaMap.Descriptor.NestedTypes[9]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<MapSfixed64Sfixed64Entry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapSfixed64Sfixed64Entry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public MapSfixed64Sfixed64Entry() { }
+        public MapSfixed64Sfixed64Entry() {
+          OnConstruction();
+        }
 
-        public MapSfixed64Sfixed64Entry(MapSfixed64Sfixed64Entry other) {
+        partial void OnConstruction();
+
+        public MapSfixed64Sfixed64Entry(MapSfixed64Sfixed64Entry other) : this() {
           key_ = other.key_;
           value_ = other.value_;
         }
@@ -5732,19 +5781,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 8, 21 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapInt32FloatEntry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestArenaMap.Descriptor.NestedTypes[10]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<MapInt32FloatEntry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapInt32FloatEntry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public MapInt32FloatEntry() { }
+        public MapInt32FloatEntry() {
+          OnConstruction();
+        }
 
-        public MapInt32FloatEntry(MapInt32FloatEntry other) {
+        partial void OnConstruction();
+
+        public MapInt32FloatEntry(MapInt32FloatEntry other) : this() {
           key_ = other.key_;
           value_ = other.value_;
         }
@@ -5870,19 +5923,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 8, 17 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapInt32DoubleEntry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestArenaMap.Descriptor.NestedTypes[11]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<MapInt32DoubleEntry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapInt32DoubleEntry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public MapInt32DoubleEntry() { }
+        public MapInt32DoubleEntry() {
+          OnConstruction();
+        }
 
-        public MapInt32DoubleEntry(MapInt32DoubleEntry other) {
+        partial void OnConstruction();
+
+        public MapInt32DoubleEntry(MapInt32DoubleEntry other) : this() {
           key_ = other.key_;
           value_ = other.value_;
         }
@@ -6008,19 +6065,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapBoolBoolEntry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestArenaMap.Descriptor.NestedTypes[12]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<MapBoolBoolEntry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapBoolBoolEntry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public MapBoolBoolEntry() { }
+        public MapBoolBoolEntry() {
+          OnConstruction();
+        }
 
-        public MapBoolBoolEntry(MapBoolBoolEntry other) {
+        partial void OnConstruction();
+
+        public MapBoolBoolEntry(MapBoolBoolEntry other) : this() {
           key_ = other.key_;
           value_ = other.value_;
         }
@@ -6146,19 +6207,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapInt32EnumEntry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestArenaMap.Descriptor.NestedTypes[13]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<MapInt32EnumEntry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapInt32EnumEntry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public MapInt32EnumEntry() { }
+        public MapInt32EnumEntry() {
+          OnConstruction();
+        }
 
-        public MapInt32EnumEntry(MapInt32EnumEntry other) {
+        partial void OnConstruction();
+
+        public MapInt32EnumEntry(MapInt32EnumEntry other) : this() {
           key_ = other.key_;
           value_ = other.value_;
         }
@@ -6284,19 +6349,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 8, 18 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapInt32ForeignMessageEntry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestArenaMap.Descriptor.NestedTypes[14]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<MapInt32ForeignMessageEntry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapInt32ForeignMessageEntry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public MapInt32ForeignMessageEntry() { }
+        public MapInt32ForeignMessageEntry() {
+          OnConstruction();
+        }
 
-        public MapInt32ForeignMessageEntry(MapInt32ForeignMessageEntry other) {
+        partial void OnConstruction();
+
+        public MapInt32ForeignMessageEntry(MapInt32ForeignMessageEntry other) : this() {
           key_ = other.key_;
           Value = other.value_ != null ? other.Value.Clone() : null;
         }
@@ -6434,19 +6503,23 @@
     private static readonly string[] _fieldNames = new string[] { "type" };
     private static readonly uint[] _fieldTags = new uint[] { 10 };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_MessageContainingEnumCalledType__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.Descriptor.MessageTypes[5]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<MessageContainingEnumCalledType> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_MessageContainingEnumCalledType__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public MessageContainingEnumCalledType() { }
+    public MessageContainingEnumCalledType() {
+      OnConstruction();
+    }
 
-    public MessageContainingEnumCalledType(MessageContainingEnumCalledType other) {
+    partial void OnConstruction();
+
+    public MessageContainingEnumCalledType(MessageContainingEnumCalledType other) : this() {
       type_ = other.type_.Clone();
     }
 
@@ -6542,19 +6615,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 8, 18 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_MessageContainingEnumCalledType_TypeEntry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType.Descriptor.NestedTypes[0]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<TypeEntry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_MessageContainingEnumCalledType_TypeEntry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public TypeEntry() { }
+        public TypeEntry() {
+          OnConstruction();
+        }
 
-        public TypeEntry(TypeEntry other) {
+        partial void OnConstruction();
+
+        public TypeEntry(TypeEntry other) : this() {
           key_ = other.key_;
           Value = other.value_ != null ? other.Value.Clone() : null;
         }
@@ -6692,19 +6769,23 @@
     private static readonly string[] _fieldNames = new string[] { "entry" };
     private static readonly uint[] _fieldTags = new uint[] { 10 };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_MessageContainingMapCalledEntry__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.Descriptor.MessageTypes[6]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<MessageContainingMapCalledEntry> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_MessageContainingMapCalledEntry__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public MessageContainingMapCalledEntry() { }
+    public MessageContainingMapCalledEntry() {
+      OnConstruction();
+    }
 
-    public MessageContainingMapCalledEntry(MessageContainingMapCalledEntry other) {
+    partial void OnConstruction();
+
+    public MessageContainingMapCalledEntry(MessageContainingMapCalledEntry other) : this() {
       entry_ = other.entry_.Clone();
     }
 
@@ -6796,19 +6877,23 @@
         private static readonly string[] _fieldNames = new string[] { "key", "value" };
         private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_MessageContainingMapCalledEntry_EntryEntry__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.MessageContainingMapCalledEntry.Descriptor.NestedTypes[0]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<EntryEntry> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_MessageContainingMapCalledEntry_EntryEntry__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public EntryEntry() { }
+        public EntryEntry() {
+          OnConstruction();
+        }
 
-        public EntryEntry(EntryEntry other) {
+        partial void OnConstruction();
+
+        public EntryEntry(EntryEntry other) : this() {
           key_ = other.key_;
           value_ = other.value_;
         }
diff --git a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportProto3.cs b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportProto3.cs
index 939be74..d30f22d 100644
--- a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportProto3.cs
+++ b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportProto3.cs
@@ -13,8 +13,7 @@
   public static partial class UnittestImportProto3 {
 
     #region Static variables
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_import_ImportMessage__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.ImportMessage> internal__static_protobuf_unittest_import_ImportMessage__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_import_ImportMessage__FieldAccessorTable;
     #endregion
     #region Descriptor
     public static pbd::FileDescriptor Descriptor {
@@ -33,17 +32,13 @@
             "UhAIEg4KCklNUE9SVF9CQVoQCUI8Chhjb20uZ29vZ2xlLnByb3RvYnVmLnRl", 
             "c3RIAfgBAaoCGkdvb2dsZS5Qcm90b2J1Zi5UZXN0UHJvdG9zUABiBnByb3Rv", 
           "Mw=="));
-      pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {
-        descriptor = root;
-        internal__static_protobuf_unittest_import_ImportMessage__Descriptor = Descriptor.MessageTypes[0];
-        internal__static_protobuf_unittest_import_ImportMessage__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.ImportMessage>(internal__static_protobuf_unittest_import_ImportMessage__Descriptor,
-                new string[] { "D", });
-      };
-      pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
+      descriptor = pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
           new pbd::FileDescriptor[] {
           global::Google.Protobuf.TestProtos.UnittestImportPublicProto3.Descriptor, 
-          }, assigner);
+          });
+      internal__static_protobuf_unittest_import_ImportMessage__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.ImportMessage), descriptor.MessageTypes[0],
+              new string[] { "D", });
     }
     #endregion
 
@@ -67,19 +62,23 @@
     private static readonly string[] _fieldNames = new string[] { "d" };
     private static readonly uint[] _fieldTags = new uint[] { 8 };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestImportProto3.internal__static_protobuf_unittest_import_ImportMessage__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestImportProto3.Descriptor.MessageTypes[0]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<ImportMessage> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestImportProto3.internal__static_protobuf_unittest_import_ImportMessage__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public ImportMessage() { }
+    public ImportMessage() {
+      OnConstruction();
+    }
 
-    public ImportMessage(ImportMessage other) {
+    partial void OnConstruction();
+
+    public ImportMessage(ImportMessage other) : this() {
       d_ = other.d_;
     }
 
diff --git a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportPublicProto3.cs b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportPublicProto3.cs
index a5a33ea..5aa03a6 100644
--- a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportPublicProto3.cs
+++ b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportPublicProto3.cs
@@ -13,8 +13,7 @@
   public static partial class UnittestImportPublicProto3 {
 
     #region Static variables
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_import_PublicImportMessage__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.PublicImportMessage> internal__static_protobuf_unittest_import_PublicImportMessage__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_import_PublicImportMessage__FieldAccessorTable;
     #endregion
     #region Descriptor
     public static pbd::FileDescriptor Descriptor {
@@ -29,16 +28,12 @@
             "bzMucHJvdG8SGHByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydCIgChNQdWJsaWNJ", 
             "bXBvcnRNZXNzYWdlEgkKAWUYASABKAVCNwoYY29tLmdvb2dsZS5wcm90b2J1", 
           "Zi50ZXN0qgIaR29vZ2xlLlByb3RvYnVmLlRlc3RQcm90b3NiBnByb3RvMw=="));
-      pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {
-        descriptor = root;
-        internal__static_protobuf_unittest_import_PublicImportMessage__Descriptor = Descriptor.MessageTypes[0];
-        internal__static_protobuf_unittest_import_PublicImportMessage__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.PublicImportMessage>(internal__static_protobuf_unittest_import_PublicImportMessage__Descriptor,
-                new string[] { "E", });
-      };
-      pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
+      descriptor = pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
           new pbd::FileDescriptor[] {
-          }, assigner);
+          });
+      internal__static_protobuf_unittest_import_PublicImportMessage__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.PublicImportMessage), descriptor.MessageTypes[0],
+              new string[] { "E", });
     }
     #endregion
 
@@ -52,19 +47,23 @@
     private static readonly string[] _fieldNames = new string[] { "e" };
     private static readonly uint[] _fieldTags = new uint[] { 8 };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestImportPublicProto3.internal__static_protobuf_unittest_import_PublicImportMessage__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestImportPublicProto3.Descriptor.MessageTypes[0]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<PublicImportMessage> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestImportPublicProto3.internal__static_protobuf_unittest_import_PublicImportMessage__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public PublicImportMessage() { }
+    public PublicImportMessage() {
+      OnConstruction();
+    }
 
-    public PublicImportMessage(PublicImportMessage other) {
+    partial void OnConstruction();
+
+    public PublicImportMessage(PublicImportMessage other) : this() {
       e_ = other.e_;
     }
 
diff --git a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestIssues.cs b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestIssues.cs
index 16bdb3f..0e409c8 100644
--- a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestIssues.cs
+++ b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestIssues.cs
@@ -13,20 +13,13 @@
   public static partial class UnittestIssues {
 
     #region Static variables
-    internal static pbd::MessageDescriptor internal__static_unittest_issues_Issue307__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.Issue307> internal__static_unittest_issues_Issue307__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_unittest_issues_Issue307_NestedOnce__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce> internal__static_unittest_issues_Issue307_NestedOnce__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_unittest_issues_Issue307_NestedOnce_NestedTwice__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Types.NestedTwice> internal__static_unittest_issues_Issue307_NestedOnce_NestedTwice__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_unittest_issues_NegativeEnumMessage__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.NegativeEnumMessage> internal__static_unittest_issues_NegativeEnumMessage__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_unittest_issues_DeprecatedChild__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.DeprecatedChild> internal__static_unittest_issues_DeprecatedChild__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_unittest_issues_DeprecatedFieldsMessage__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage> internal__static_unittest_issues_DeprecatedFieldsMessage__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_unittest_issues_ItemField__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.ItemField> internal__static_unittest_issues_ItemField__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_unittest_issues_Issue307__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_unittest_issues_Issue307_NestedOnce__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_unittest_issues_Issue307_NestedOnce_NestedTwice__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_unittest_issues_NegativeEnumMessage__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_unittest_issues_DeprecatedChild__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_unittest_issues_DeprecatedFieldsMessage__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_unittest_issues_ItemField__FieldAccessorTable;
     #endregion
     #region Descriptor
     public static pbd::FileDescriptor Descriptor {
@@ -55,40 +48,30 @@
             "EPv//////////wESFQoITWludXNPbmUQ////////////ASouCg5EZXByZWNh", 
             "dGVkRW51bRITCg9ERVBSRUNBVEVEX1pFUk8QABIHCgNvbmUQAUIfSAGqAhpV", 
           "bml0VGVzdC5Jc3N1ZXMuVGVzdFByb3Rvc2IGcHJvdG8z"));
-      pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {
-        descriptor = root;
-        internal__static_unittest_issues_Issue307__Descriptor = Descriptor.MessageTypes[0];
-        internal__static_unittest_issues_Issue307__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.Issue307>(internal__static_unittest_issues_Issue307__Descriptor,
-                new string[] { });
-        internal__static_unittest_issues_Issue307_NestedOnce__Descriptor = internal__static_unittest_issues_Issue307__Descriptor.NestedTypes[0];
-        internal__static_unittest_issues_Issue307_NestedOnce__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce>(internal__static_unittest_issues_Issue307_NestedOnce__Descriptor,
-                new string[] { });
-        internal__static_unittest_issues_Issue307_NestedOnce_NestedTwice__Descriptor = internal__static_unittest_issues_Issue307_NestedOnce__Descriptor.NestedTypes[0];
-        internal__static_unittest_issues_Issue307_NestedOnce_NestedTwice__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Types.NestedTwice>(internal__static_unittest_issues_Issue307_NestedOnce_NestedTwice__Descriptor,
-                new string[] { });
-        internal__static_unittest_issues_NegativeEnumMessage__Descriptor = Descriptor.MessageTypes[1];
-        internal__static_unittest_issues_NegativeEnumMessage__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.NegativeEnumMessage>(internal__static_unittest_issues_NegativeEnumMessage__Descriptor,
-                new string[] { "Value", "Values", "PackedValues", });
-        internal__static_unittest_issues_DeprecatedChild__Descriptor = Descriptor.MessageTypes[2];
-        internal__static_unittest_issues_DeprecatedChild__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.DeprecatedChild>(internal__static_unittest_issues_DeprecatedChild__Descriptor,
-                new string[] { });
-        internal__static_unittest_issues_DeprecatedFieldsMessage__Descriptor = Descriptor.MessageTypes[3];
-        internal__static_unittest_issues_DeprecatedFieldsMessage__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage>(internal__static_unittest_issues_DeprecatedFieldsMessage__Descriptor,
-                new string[] { "PrimitiveValue", "PrimitiveArray", "MessageValue", "MessageArray", "EnumValue", "EnumArray", });
-        internal__static_unittest_issues_ItemField__Descriptor = Descriptor.MessageTypes[4];
-        internal__static_unittest_issues_ItemField__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.ItemField>(internal__static_unittest_issues_ItemField__Descriptor,
-                new string[] { "Item", });
-      };
-      pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
+      descriptor = pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
           new pbd::FileDescriptor[] {
-          }, assigner);
+          });
+      internal__static_unittest_issues_Issue307__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::UnitTest.Issues.TestProtos.Issue307), descriptor.MessageTypes[0],
+              new string[] { });
+      internal__static_unittest_issues_Issue307_NestedOnce__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce), descriptor.MessageTypes[0].NestedTypes[0],
+              new string[] { });
+      internal__static_unittest_issues_Issue307_NestedOnce_NestedTwice__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Types.NestedTwice), descriptor.MessageTypes[0].NestedTypes[0].NestedTypes[0],
+              new string[] { });
+      internal__static_unittest_issues_NegativeEnumMessage__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::UnitTest.Issues.TestProtos.NegativeEnumMessage), descriptor.MessageTypes[1],
+              new string[] { "Value", "Values", "PackedValues", });
+      internal__static_unittest_issues_DeprecatedChild__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::UnitTest.Issues.TestProtos.DeprecatedChild), descriptor.MessageTypes[2],
+              new string[] { });
+      internal__static_unittest_issues_DeprecatedFieldsMessage__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage), descriptor.MessageTypes[3],
+              new string[] { "PrimitiveValue", "PrimitiveArray", "MessageValue", "MessageArray", "EnumValue", "EnumArray", });
+      internal__static_unittest_issues_ItemField__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::UnitTest.Issues.TestProtos.ItemField), descriptor.MessageTypes[4],
+              new string[] { "Item", });
     }
     #endregion
 
@@ -116,19 +99,23 @@
     private static readonly string[] _fieldNames = new string[] {  };
     private static readonly uint[] _fieldTags = new uint[] {  };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_Issue307__Descriptor; }
+      get { return global::UnitTest.Issues.TestProtos.UnittestIssues.Descriptor.MessageTypes[0]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<Issue307> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_Issue307__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public Issue307() { }
+    public Issue307() {
+      OnConstruction();
+    }
 
-    public Issue307(Issue307 other) {
+    partial void OnConstruction();
+
+    public Issue307(Issue307 other) : this() {
     }
 
     public Issue307 Clone() {
@@ -201,19 +188,23 @@
         private static readonly string[] _fieldNames = new string[] {  };
         private static readonly uint[] _fieldTags = new uint[] {  };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_Issue307_NestedOnce__Descriptor; }
+          get { return global::UnitTest.Issues.TestProtos.Issue307.Descriptor.NestedTypes[0]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<NestedOnce> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_Issue307_NestedOnce__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public NestedOnce() { }
+        public NestedOnce() {
+          OnConstruction();
+        }
 
-        public NestedOnce(NestedOnce other) {
+        partial void OnConstruction();
+
+        public NestedOnce(NestedOnce other) : this() {
         }
 
         public NestedOnce Clone() {
@@ -286,19 +277,23 @@
             private static readonly string[] _fieldNames = new string[] {  };
             private static readonly uint[] _fieldTags = new uint[] {  };
             public static pbd::MessageDescriptor Descriptor {
-              get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_Issue307_NestedOnce_NestedTwice__Descriptor; }
+              get { return global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Descriptor.NestedTypes[0]; }
             }
 
-            public pb::FieldAccess.FieldAccessorTable<NestedTwice> Fields {
+            public pb::FieldAccess.FieldAccessorTable Fields {
               get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_Issue307_NestedOnce_NestedTwice__FieldAccessorTable; }
             }
 
             private bool _frozen = false;
             public bool IsFrozen { get { return _frozen; } }
 
-            public NestedTwice() { }
+            public NestedTwice() {
+              OnConstruction();
+            }
 
-            public NestedTwice(NestedTwice other) {
+            partial void OnConstruction();
+
+            public NestedTwice(NestedTwice other) : this() {
             }
 
             public NestedTwice Clone() {
@@ -380,19 +375,23 @@
     private static readonly string[] _fieldNames = new string[] { "packed_values", "value", "values" };
     private static readonly uint[] _fieldTags = new uint[] { 26, 8, 16 };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_NegativeEnumMessage__Descriptor; }
+      get { return global::UnitTest.Issues.TestProtos.UnittestIssues.Descriptor.MessageTypes[1]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<NegativeEnumMessage> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_NegativeEnumMessage__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public NegativeEnumMessage() { }
+    public NegativeEnumMessage() {
+      OnConstruction();
+    }
 
-    public NegativeEnumMessage(NegativeEnumMessage other) {
+    partial void OnConstruction();
+
+    public NegativeEnumMessage(NegativeEnumMessage other) : this() {
       value_ = other.value_;
       values_ = other.values_.Clone();
       packedValues_ = other.packedValues_.Clone();
@@ -529,19 +528,23 @@
     private static readonly string[] _fieldNames = new string[] {  };
     private static readonly uint[] _fieldTags = new uint[] {  };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_DeprecatedChild__Descriptor; }
+      get { return global::UnitTest.Issues.TestProtos.UnittestIssues.Descriptor.MessageTypes[2]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<DeprecatedChild> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_DeprecatedChild__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public DeprecatedChild() { }
+    public DeprecatedChild() {
+      OnConstruction();
+    }
 
-    public DeprecatedChild(DeprecatedChild other) {
+    partial void OnConstruction();
+
+    public DeprecatedChild(DeprecatedChild other) : this() {
     }
 
     public DeprecatedChild Clone() {
@@ -613,19 +616,23 @@
     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 pbd::MessageDescriptor Descriptor {
-      get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_DeprecatedFieldsMessage__Descriptor; }
+      get { return global::UnitTest.Issues.TestProtos.UnittestIssues.Descriptor.MessageTypes[3]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<DeprecatedFieldsMessage> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_DeprecatedFieldsMessage__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public DeprecatedFieldsMessage() { }
+    public DeprecatedFieldsMessage() {
+      OnConstruction();
+    }
 
-    public DeprecatedFieldsMessage(DeprecatedFieldsMessage other) {
+    partial void OnConstruction();
+
+    public DeprecatedFieldsMessage(DeprecatedFieldsMessage other) : this() {
       primitiveValue_ = other.primitiveValue_;
       primitiveArray_ = other.primitiveArray_.Clone();
       MessageValue = other.messageValue_ != null ? other.MessageValue.Clone() : null;
@@ -849,19 +856,23 @@
     private static readonly string[] _fieldNames = new string[] { "item" };
     private static readonly uint[] _fieldTags = new uint[] { 8 };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_ItemField__Descriptor; }
+      get { return global::UnitTest.Issues.TestProtos.UnittestIssues.Descriptor.MessageTypes[4]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<ItemField> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_ItemField__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public ItemField() { }
+    public ItemField() {
+      OnConstruction();
+    }
 
-    public ItemField(ItemField other) {
+    partial void OnConstruction();
+
+    public ItemField(ItemField other) : this() {
       item_ = other.item_;
     }
 
diff --git a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestProto3.cs b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestProto3.cs
index ea486fc..d2437bf 100644
--- a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestProto3.cs
+++ b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestProto3.cs
@@ -13,76 +13,41 @@
   public static partial class UnittestProto3 {
 
     #region Static variables
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestAllTypes__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestAllTypes> internal__static_protobuf_unittest_TestAllTypes__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestAllTypes_NestedMessage__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage> internal__static_protobuf_unittest_TestAllTypes_NestedMessage__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_NestedTestAllTypes__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.NestedTestAllTypes> internal__static_protobuf_unittest_NestedTestAllTypes__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestDeprecatedFields__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestDeprecatedFields> internal__static_protobuf_unittest_TestDeprecatedFields__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_ForeignMessage__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.ForeignMessage> internal__static_protobuf_unittest_ForeignMessage__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestReservedFields__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestReservedFields> internal__static_protobuf_unittest_TestReservedFields__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestForeignNested__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestForeignNested> internal__static_protobuf_unittest_TestForeignNested__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestReallyLargeTagNumber__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestReallyLargeTagNumber> internal__static_protobuf_unittest_TestReallyLargeTagNumber__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestRecursiveMessage__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestRecursiveMessage> internal__static_protobuf_unittest_TestRecursiveMessage__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMutualRecursionA__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMutualRecursionA> internal__static_protobuf_unittest_TestMutualRecursionA__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMutualRecursionB__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMutualRecursionB> internal__static_protobuf_unittest_TestMutualRecursionB__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestCamelCaseFieldNames__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestCamelCaseFieldNames> internal__static_protobuf_unittest_TestCamelCaseFieldNames__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestFieldOrderings__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestFieldOrderings> internal__static_protobuf_unittest_TestFieldOrderings__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestFieldOrderings_NestedMessage__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage> internal__static_protobuf_unittest_TestFieldOrderings_NestedMessage__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_SparseEnumMessage__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.SparseEnumMessage> internal__static_protobuf_unittest_SparseEnumMessage__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_OneString__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.OneString> internal__static_protobuf_unittest_OneString__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_MoreString__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.MoreString> internal__static_protobuf_unittest_MoreString__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_OneBytes__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.OneBytes> internal__static_protobuf_unittest_OneBytes__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_MoreBytes__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.MoreBytes> internal__static_protobuf_unittest_MoreBytes__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_Int32Message__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.Int32Message> internal__static_protobuf_unittest_Int32Message__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_Uint32Message__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.Uint32Message> internal__static_protobuf_unittest_Uint32Message__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_Int64Message__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.Int64Message> internal__static_protobuf_unittest_Int64Message__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_Uint64Message__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.Uint64Message> internal__static_protobuf_unittest_Uint64Message__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_BoolMessage__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.BoolMessage> internal__static_protobuf_unittest_BoolMessage__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestOneof__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestOneof> internal__static_protobuf_unittest_TestOneof__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestPackedTypes__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestPackedTypes> internal__static_protobuf_unittest_TestPackedTypes__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestUnpackedTypes__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestUnpackedTypes> internal__static_protobuf_unittest_TestUnpackedTypes__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestRepeatedScalarDifferentTagSizes__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestRepeatedScalarDifferentTagSizes> internal__static_protobuf_unittest_TestRepeatedScalarDifferentTagSizes__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestCommentInjectionMessage__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestCommentInjectionMessage> internal__static_protobuf_unittest_TestCommentInjectionMessage__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_FooRequest__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.FooRequest> internal__static_protobuf_unittest_FooRequest__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_FooResponse__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.FooResponse> internal__static_protobuf_unittest_FooResponse__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_FooClientMessage__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.FooClientMessage> internal__static_protobuf_unittest_FooClientMessage__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_FooServerMessage__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.FooServerMessage> internal__static_protobuf_unittest_FooServerMessage__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_BarRequest__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.BarRequest> internal__static_protobuf_unittest_BarRequest__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_BarResponse__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.BarResponse> internal__static_protobuf_unittest_BarResponse__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestAllTypes__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestAllTypes_NestedMessage__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_NestedTestAllTypes__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestDeprecatedFields__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_ForeignMessage__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestReservedFields__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestForeignNested__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestReallyLargeTagNumber__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestRecursiveMessage__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestMutualRecursionA__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestMutualRecursionB__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestCamelCaseFieldNames__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestFieldOrderings__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestFieldOrderings_NestedMessage__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_SparseEnumMessage__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_OneString__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_MoreString__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_OneBytes__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_MoreBytes__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_Int32Message__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_Uint32Message__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_Int64Message__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_Uint64Message__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_BoolMessage__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestOneof__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestPackedTypes__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestUnpackedTypes__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestRepeatedScalarDifferentTagSizes__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestCommentInjectionMessage__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_FooRequest__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_FooResponse__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_FooClientMessage__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_FooServerMessage__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_BarRequest__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_BarResponse__FieldAccessorTable;
     #endregion
     #region Descriptor
     public static pbd::FileDescriptor Descriptor {
@@ -220,153 +185,115 @@
             "HS5wcm90b2J1Zl91bml0dGVzdC5CYXJSZXF1ZXN0Gh4ucHJvdG9idWZfdW5p", 
             "dHRlc3QuQmFyUmVzcG9uc2VCOkINVW5pdHRlc3RQcm90b0gBgAEBiAEBkAEB", 
           "+AEBqgIaR29vZ2xlLlByb3RvYnVmLlRlc3RQcm90b3NiBnByb3RvMw=="));
-      pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {
-        descriptor = root;
-        internal__static_protobuf_unittest_TestAllTypes__Descriptor = Descriptor.MessageTypes[0];
-        internal__static_protobuf_unittest_TestAllTypes__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestAllTypes>(internal__static_protobuf_unittest_TestAllTypes__Descriptor,
-                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", "OneofField", });
-        internal__static_protobuf_unittest_TestAllTypes_NestedMessage__Descriptor = internal__static_protobuf_unittest_TestAllTypes__Descriptor.NestedTypes[0];
-        internal__static_protobuf_unittest_TestAllTypes_NestedMessage__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage>(internal__static_protobuf_unittest_TestAllTypes_NestedMessage__Descriptor,
-                new string[] { "Bb", });
-        internal__static_protobuf_unittest_NestedTestAllTypes__Descriptor = Descriptor.MessageTypes[1];
-        internal__static_protobuf_unittest_NestedTestAllTypes__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.NestedTestAllTypes>(internal__static_protobuf_unittest_NestedTestAllTypes__Descriptor,
-                new string[] { "Child", "Payload", "RepeatedChild", });
-        internal__static_protobuf_unittest_TestDeprecatedFields__Descriptor = Descriptor.MessageTypes[2];
-        internal__static_protobuf_unittest_TestDeprecatedFields__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestDeprecatedFields>(internal__static_protobuf_unittest_TestDeprecatedFields__Descriptor,
-                new string[] { "DeprecatedInt32", });
-        internal__static_protobuf_unittest_ForeignMessage__Descriptor = Descriptor.MessageTypes[3];
-        internal__static_protobuf_unittest_ForeignMessage__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.ForeignMessage>(internal__static_protobuf_unittest_ForeignMessage__Descriptor,
-                new string[] { "C", });
-        internal__static_protobuf_unittest_TestReservedFields__Descriptor = Descriptor.MessageTypes[4];
-        internal__static_protobuf_unittest_TestReservedFields__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestReservedFields>(internal__static_protobuf_unittest_TestReservedFields__Descriptor,
-                new string[] { });
-        internal__static_protobuf_unittest_TestForeignNested__Descriptor = Descriptor.MessageTypes[5];
-        internal__static_protobuf_unittest_TestForeignNested__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestForeignNested>(internal__static_protobuf_unittest_TestForeignNested__Descriptor,
-                new string[] { "ForeignNested", });
-        internal__static_protobuf_unittest_TestReallyLargeTagNumber__Descriptor = Descriptor.MessageTypes[6];
-        internal__static_protobuf_unittest_TestReallyLargeTagNumber__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestReallyLargeTagNumber>(internal__static_protobuf_unittest_TestReallyLargeTagNumber__Descriptor,
-                new string[] { "A", "Bb", });
-        internal__static_protobuf_unittest_TestRecursiveMessage__Descriptor = Descriptor.MessageTypes[7];
-        internal__static_protobuf_unittest_TestRecursiveMessage__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestRecursiveMessage>(internal__static_protobuf_unittest_TestRecursiveMessage__Descriptor,
-                new string[] { "A", "I", });
-        internal__static_protobuf_unittest_TestMutualRecursionA__Descriptor = Descriptor.MessageTypes[8];
-        internal__static_protobuf_unittest_TestMutualRecursionA__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMutualRecursionA>(internal__static_protobuf_unittest_TestMutualRecursionA__Descriptor,
-                new string[] { "Bb", });
-        internal__static_protobuf_unittest_TestMutualRecursionB__Descriptor = Descriptor.MessageTypes[9];
-        internal__static_protobuf_unittest_TestMutualRecursionB__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMutualRecursionB>(internal__static_protobuf_unittest_TestMutualRecursionB__Descriptor,
-                new string[] { "A", "OptionalInt32", });
-        internal__static_protobuf_unittest_TestCamelCaseFieldNames__Descriptor = Descriptor.MessageTypes[10];
-        internal__static_protobuf_unittest_TestCamelCaseFieldNames__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestCamelCaseFieldNames>(internal__static_protobuf_unittest_TestCamelCaseFieldNames__Descriptor,
-                new string[] { "PrimitiveField", "StringField", "EnumField", "MessageField", "RepeatedPrimitiveField", "RepeatedStringField", "RepeatedEnumField", "RepeatedMessageField", });
-        internal__static_protobuf_unittest_TestFieldOrderings__Descriptor = Descriptor.MessageTypes[11];
-        internal__static_protobuf_unittest_TestFieldOrderings__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestFieldOrderings>(internal__static_protobuf_unittest_TestFieldOrderings__Descriptor,
-                new string[] { "MyString", "MyInt", "MyFloat", "SingleNestedMessage", });
-        internal__static_protobuf_unittest_TestFieldOrderings_NestedMessage__Descriptor = internal__static_protobuf_unittest_TestFieldOrderings__Descriptor.NestedTypes[0];
-        internal__static_protobuf_unittest_TestFieldOrderings_NestedMessage__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage>(internal__static_protobuf_unittest_TestFieldOrderings_NestedMessage__Descriptor,
-                new string[] { "Oo", "Bb", });
-        internal__static_protobuf_unittest_SparseEnumMessage__Descriptor = Descriptor.MessageTypes[12];
-        internal__static_protobuf_unittest_SparseEnumMessage__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.SparseEnumMessage>(internal__static_protobuf_unittest_SparseEnumMessage__Descriptor,
-                new string[] { "SparseEnum", });
-        internal__static_protobuf_unittest_OneString__Descriptor = Descriptor.MessageTypes[13];
-        internal__static_protobuf_unittest_OneString__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.OneString>(internal__static_protobuf_unittest_OneString__Descriptor,
-                new string[] { "Data", });
-        internal__static_protobuf_unittest_MoreString__Descriptor = Descriptor.MessageTypes[14];
-        internal__static_protobuf_unittest_MoreString__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.MoreString>(internal__static_protobuf_unittest_MoreString__Descriptor,
-                new string[] { "Data", });
-        internal__static_protobuf_unittest_OneBytes__Descriptor = Descriptor.MessageTypes[15];
-        internal__static_protobuf_unittest_OneBytes__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.OneBytes>(internal__static_protobuf_unittest_OneBytes__Descriptor,
-                new string[] { "Data", });
-        internal__static_protobuf_unittest_MoreBytes__Descriptor = Descriptor.MessageTypes[16];
-        internal__static_protobuf_unittest_MoreBytes__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.MoreBytes>(internal__static_protobuf_unittest_MoreBytes__Descriptor,
-                new string[] { "Data", });
-        internal__static_protobuf_unittest_Int32Message__Descriptor = Descriptor.MessageTypes[17];
-        internal__static_protobuf_unittest_Int32Message__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.Int32Message>(internal__static_protobuf_unittest_Int32Message__Descriptor,
-                new string[] { "Data", });
-        internal__static_protobuf_unittest_Uint32Message__Descriptor = Descriptor.MessageTypes[18];
-        internal__static_protobuf_unittest_Uint32Message__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.Uint32Message>(internal__static_protobuf_unittest_Uint32Message__Descriptor,
-                new string[] { "Data", });
-        internal__static_protobuf_unittest_Int64Message__Descriptor = Descriptor.MessageTypes[19];
-        internal__static_protobuf_unittest_Int64Message__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.Int64Message>(internal__static_protobuf_unittest_Int64Message__Descriptor,
-                new string[] { "Data", });
-        internal__static_protobuf_unittest_Uint64Message__Descriptor = Descriptor.MessageTypes[20];
-        internal__static_protobuf_unittest_Uint64Message__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.Uint64Message>(internal__static_protobuf_unittest_Uint64Message__Descriptor,
-                new string[] { "Data", });
-        internal__static_protobuf_unittest_BoolMessage__Descriptor = Descriptor.MessageTypes[21];
-        internal__static_protobuf_unittest_BoolMessage__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.BoolMessage>(internal__static_protobuf_unittest_BoolMessage__Descriptor,
-                new string[] { "Data", });
-        internal__static_protobuf_unittest_TestOneof__Descriptor = Descriptor.MessageTypes[22];
-        internal__static_protobuf_unittest_TestOneof__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestOneof>(internal__static_protobuf_unittest_TestOneof__Descriptor,
-                new string[] { "FooInt", "FooString", "FooMessage", "Foo", });
-        internal__static_protobuf_unittest_TestPackedTypes__Descriptor = Descriptor.MessageTypes[23];
-        internal__static_protobuf_unittest_TestPackedTypes__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestPackedTypes>(internal__static_protobuf_unittest_TestPackedTypes__Descriptor,
-                new string[] { "PackedInt32", "PackedInt64", "PackedUint32", "PackedUint64", "PackedSint32", "PackedSint64", "PackedFixed32", "PackedFixed64", "PackedSfixed32", "PackedSfixed64", "PackedFloat", "PackedDouble", "PackedBool", "PackedEnum", });
-        internal__static_protobuf_unittest_TestUnpackedTypes__Descriptor = Descriptor.MessageTypes[24];
-        internal__static_protobuf_unittest_TestUnpackedTypes__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestUnpackedTypes>(internal__static_protobuf_unittest_TestUnpackedTypes__Descriptor,
-                new string[] { "UnpackedInt32", "UnpackedInt64", "UnpackedUint32", "UnpackedUint64", "UnpackedSint32", "UnpackedSint64", "UnpackedFixed32", "UnpackedFixed64", "UnpackedSfixed32", "UnpackedSfixed64", "UnpackedFloat", "UnpackedDouble", "UnpackedBool", "UnpackedEnum", });
-        internal__static_protobuf_unittest_TestRepeatedScalarDifferentTagSizes__Descriptor = Descriptor.MessageTypes[25];
-        internal__static_protobuf_unittest_TestRepeatedScalarDifferentTagSizes__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestRepeatedScalarDifferentTagSizes>(internal__static_protobuf_unittest_TestRepeatedScalarDifferentTagSizes__Descriptor,
-                new string[] { "RepeatedFixed32", "RepeatedInt32", "RepeatedFixed64", "RepeatedInt64", "RepeatedFloat", "RepeatedUint64", });
-        internal__static_protobuf_unittest_TestCommentInjectionMessage__Descriptor = Descriptor.MessageTypes[26];
-        internal__static_protobuf_unittest_TestCommentInjectionMessage__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestCommentInjectionMessage>(internal__static_protobuf_unittest_TestCommentInjectionMessage__Descriptor,
-                new string[] { "A", });
-        internal__static_protobuf_unittest_FooRequest__Descriptor = Descriptor.MessageTypes[27];
-        internal__static_protobuf_unittest_FooRequest__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.FooRequest>(internal__static_protobuf_unittest_FooRequest__Descriptor,
-                new string[] { });
-        internal__static_protobuf_unittest_FooResponse__Descriptor = Descriptor.MessageTypes[28];
-        internal__static_protobuf_unittest_FooResponse__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.FooResponse>(internal__static_protobuf_unittest_FooResponse__Descriptor,
-                new string[] { });
-        internal__static_protobuf_unittest_FooClientMessage__Descriptor = Descriptor.MessageTypes[29];
-        internal__static_protobuf_unittest_FooClientMessage__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.FooClientMessage>(internal__static_protobuf_unittest_FooClientMessage__Descriptor,
-                new string[] { });
-        internal__static_protobuf_unittest_FooServerMessage__Descriptor = Descriptor.MessageTypes[30];
-        internal__static_protobuf_unittest_FooServerMessage__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.FooServerMessage>(internal__static_protobuf_unittest_FooServerMessage__Descriptor,
-                new string[] { });
-        internal__static_protobuf_unittest_BarRequest__Descriptor = Descriptor.MessageTypes[31];
-        internal__static_protobuf_unittest_BarRequest__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.BarRequest>(internal__static_protobuf_unittest_BarRequest__Descriptor,
-                new string[] { });
-        internal__static_protobuf_unittest_BarResponse__Descriptor = Descriptor.MessageTypes[32];
-        internal__static_protobuf_unittest_BarResponse__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.BarResponse>(internal__static_protobuf_unittest_BarResponse__Descriptor,
-                new string[] { });
-      };
-      pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
+      descriptor = pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
           new pbd::FileDescriptor[] {
           global::Google.Protobuf.TestProtos.UnittestImportProto3.Descriptor, 
-          }, assigner);
+          });
+      internal__static_protobuf_unittest_TestAllTypes__FieldAccessorTable = 
+          new pb::FieldAccess.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", "OneofField", });
+      internal__static_protobuf_unittest_TestAllTypes_NestedMessage__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage), descriptor.MessageTypes[0].NestedTypes[0],
+              new string[] { "Bb", });
+      internal__static_protobuf_unittest_NestedTestAllTypes__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.NestedTestAllTypes), descriptor.MessageTypes[1],
+              new string[] { "Child", "Payload", "RepeatedChild", });
+      internal__static_protobuf_unittest_TestDeprecatedFields__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestDeprecatedFields), descriptor.MessageTypes[2],
+              new string[] { "DeprecatedInt32", });
+      internal__static_protobuf_unittest_ForeignMessage__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.ForeignMessage), descriptor.MessageTypes[3],
+              new string[] { "C", });
+      internal__static_protobuf_unittest_TestReservedFields__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestReservedFields), descriptor.MessageTypes[4],
+              new string[] { });
+      internal__static_protobuf_unittest_TestForeignNested__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestForeignNested), descriptor.MessageTypes[5],
+              new string[] { "ForeignNested", });
+      internal__static_protobuf_unittest_TestReallyLargeTagNumber__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestReallyLargeTagNumber), descriptor.MessageTypes[6],
+              new string[] { "A", "Bb", });
+      internal__static_protobuf_unittest_TestRecursiveMessage__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestRecursiveMessage), descriptor.MessageTypes[7],
+              new string[] { "A", "I", });
+      internal__static_protobuf_unittest_TestMutualRecursionA__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestMutualRecursionA), descriptor.MessageTypes[8],
+              new string[] { "Bb", });
+      internal__static_protobuf_unittest_TestMutualRecursionB__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestMutualRecursionB), descriptor.MessageTypes[9],
+              new string[] { "A", "OptionalInt32", });
+      internal__static_protobuf_unittest_TestCamelCaseFieldNames__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestCamelCaseFieldNames), descriptor.MessageTypes[10],
+              new string[] { "PrimitiveField", "StringField", "EnumField", "MessageField", "RepeatedPrimitiveField", "RepeatedStringField", "RepeatedEnumField", "RepeatedMessageField", });
+      internal__static_protobuf_unittest_TestFieldOrderings__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestFieldOrderings), descriptor.MessageTypes[11],
+              new string[] { "MyString", "MyInt", "MyFloat", "SingleNestedMessage", });
+      internal__static_protobuf_unittest_TestFieldOrderings_NestedMessage__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage), descriptor.MessageTypes[11].NestedTypes[0],
+              new string[] { "Oo", "Bb", });
+      internal__static_protobuf_unittest_SparseEnumMessage__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.SparseEnumMessage), descriptor.MessageTypes[12],
+              new string[] { "SparseEnum", });
+      internal__static_protobuf_unittest_OneString__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.OneString), descriptor.MessageTypes[13],
+              new string[] { "Data", });
+      internal__static_protobuf_unittest_MoreString__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.MoreString), descriptor.MessageTypes[14],
+              new string[] { "Data", });
+      internal__static_protobuf_unittest_OneBytes__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.OneBytes), descriptor.MessageTypes[15],
+              new string[] { "Data", });
+      internal__static_protobuf_unittest_MoreBytes__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.MoreBytes), descriptor.MessageTypes[16],
+              new string[] { "Data", });
+      internal__static_protobuf_unittest_Int32Message__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.Int32Message), descriptor.MessageTypes[17],
+              new string[] { "Data", });
+      internal__static_protobuf_unittest_Uint32Message__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.Uint32Message), descriptor.MessageTypes[18],
+              new string[] { "Data", });
+      internal__static_protobuf_unittest_Int64Message__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.Int64Message), descriptor.MessageTypes[19],
+              new string[] { "Data", });
+      internal__static_protobuf_unittest_Uint64Message__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.Uint64Message), descriptor.MessageTypes[20],
+              new string[] { "Data", });
+      internal__static_protobuf_unittest_BoolMessage__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.BoolMessage), descriptor.MessageTypes[21],
+              new string[] { "Data", });
+      internal__static_protobuf_unittest_TestOneof__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestOneof), descriptor.MessageTypes[22],
+              new string[] { "FooInt", "FooString", "FooMessage", "Foo", });
+      internal__static_protobuf_unittest_TestPackedTypes__FieldAccessorTable = 
+          new pb::FieldAccess.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", });
+      internal__static_protobuf_unittest_TestUnpackedTypes__FieldAccessorTable = 
+          new pb::FieldAccess.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", });
+      internal__static_protobuf_unittest_TestRepeatedScalarDifferentTagSizes__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestRepeatedScalarDifferentTagSizes), descriptor.MessageTypes[25],
+              new string[] { "RepeatedFixed32", "RepeatedInt32", "RepeatedFixed64", "RepeatedInt64", "RepeatedFloat", "RepeatedUint64", });
+      internal__static_protobuf_unittest_TestCommentInjectionMessage__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.TestCommentInjectionMessage), descriptor.MessageTypes[26],
+              new string[] { "A", });
+      internal__static_protobuf_unittest_FooRequest__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.FooRequest), descriptor.MessageTypes[27],
+              new string[] { });
+      internal__static_protobuf_unittest_FooResponse__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.FooResponse), descriptor.MessageTypes[28],
+              new string[] { });
+      internal__static_protobuf_unittest_FooClientMessage__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.FooClientMessage), descriptor.MessageTypes[29],
+              new string[] { });
+      internal__static_protobuf_unittest_FooServerMessage__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.FooServerMessage), descriptor.MessageTypes[30],
+              new string[] { });
+      internal__static_protobuf_unittest_BarRequest__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.BarRequest), descriptor.MessageTypes[31],
+              new string[] { });
+      internal__static_protobuf_unittest_BarResponse__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.TestProtos.BarResponse), descriptor.MessageTypes[32],
+              new string[] { });
     }
     #endregion
 
@@ -409,19 +336,23 @@
     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 pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestAllTypes__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[0]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<TestAllTypes> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestAllTypes__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public TestAllTypes() { }
+    public TestAllTypes() {
+      OnConstruction();
+    }
 
-    public TestAllTypes(TestAllTypes other) {
+    partial void OnConstruction();
+
+    public TestAllTypes(TestAllTypes other) : this() {
       singleInt32_ = other.singleInt32_;
       singleInt64_ = other.singleInt64_;
       singleUint32_ = other.singleUint32_;
@@ -1702,19 +1633,23 @@
         private static readonly string[] _fieldNames = new string[] { "bb" };
         private static readonly uint[] _fieldTags = new uint[] { 8 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestAllTypes_NestedMessage__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestAllTypes.Descriptor.NestedTypes[0]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<NestedMessage> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestAllTypes_NestedMessage__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public NestedMessage() { }
+        public NestedMessage() {
+          OnConstruction();
+        }
 
-        public NestedMessage(NestedMessage other) {
+        partial void OnConstruction();
+
+        public NestedMessage(NestedMessage other) : this() {
           bb_ = other.bb_;
         }
 
@@ -1818,19 +1753,23 @@
     private static readonly string[] _fieldNames = new string[] { "child", "payload", "repeated_child" };
     private static readonly uint[] _fieldTags = new uint[] { 10, 18, 26 };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_NestedTestAllTypes__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[1]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<NestedTestAllTypes> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_NestedTestAllTypes__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public NestedTestAllTypes() { }
+    public NestedTestAllTypes() {
+      OnConstruction();
+    }
 
-    public NestedTestAllTypes(NestedTestAllTypes other) {
+    partial void OnConstruction();
+
+    public NestedTestAllTypes(NestedTestAllTypes other) : this() {
       Child = other.child_ != null ? other.Child.Clone() : null;
       Payload = other.payload_ != null ? other.Payload.Clone() : null;
       repeatedChild_ = other.repeatedChild_.Clone();
@@ -1989,19 +1928,23 @@
     private static readonly string[] _fieldNames = new string[] { "deprecated_int32" };
     private static readonly uint[] _fieldTags = new uint[] { 8 };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestDeprecatedFields__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[2]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<TestDeprecatedFields> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestDeprecatedFields__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public TestDeprecatedFields() { }
+    public TestDeprecatedFields() {
+      OnConstruction();
+    }
 
-    public TestDeprecatedFields(TestDeprecatedFields other) {
+    partial void OnConstruction();
+
+    public TestDeprecatedFields(TestDeprecatedFields other) : this() {
       deprecatedInt32_ = other.deprecatedInt32_;
     }
 
@@ -2101,19 +2044,23 @@
     private static readonly string[] _fieldNames = new string[] { "c" };
     private static readonly uint[] _fieldTags = new uint[] { 8 };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_ForeignMessage__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[3]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<ForeignMessage> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_ForeignMessage__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public ForeignMessage() { }
+    public ForeignMessage() {
+      OnConstruction();
+    }
 
-    public ForeignMessage(ForeignMessage other) {
+    partial void OnConstruction();
+
+    public ForeignMessage(ForeignMessage other) : this() {
       c_ = other.c_;
     }
 
@@ -2212,19 +2159,23 @@
     private static readonly string[] _fieldNames = new string[] {  };
     private static readonly uint[] _fieldTags = new uint[] {  };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestReservedFields__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[4]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<TestReservedFields> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestReservedFields__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public TestReservedFields() { }
+    public TestReservedFields() {
+      OnConstruction();
+    }
 
-    public TestReservedFields(TestReservedFields other) {
+    partial void OnConstruction();
+
+    public TestReservedFields(TestReservedFields other) : this() {
     }
 
     public TestReservedFields Clone() {
@@ -2296,19 +2247,23 @@
     private static readonly string[] _fieldNames = new string[] { "foreign_nested" };
     private static readonly uint[] _fieldTags = new uint[] { 10 };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestForeignNested__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[5]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<TestForeignNested> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestForeignNested__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public TestForeignNested() { }
+    public TestForeignNested() {
+      OnConstruction();
+    }
 
-    public TestForeignNested(TestForeignNested other) {
+    partial void OnConstruction();
+
+    public TestForeignNested(TestForeignNested other) : this() {
       ForeignNested = other.foreignNested_ != null ? other.ForeignNested.Clone() : null;
     }
 
@@ -2414,19 +2369,23 @@
     private static readonly string[] _fieldNames = new string[] { "a", "bb" };
     private static readonly uint[] _fieldTags = new uint[] { 8, 2147483640 };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestReallyLargeTagNumber__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[6]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<TestReallyLargeTagNumber> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestReallyLargeTagNumber__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public TestReallyLargeTagNumber() { }
+    public TestReallyLargeTagNumber() {
+      OnConstruction();
+    }
 
-    public TestReallyLargeTagNumber(TestReallyLargeTagNumber other) {
+    partial void OnConstruction();
+
+    public TestReallyLargeTagNumber(TestReallyLargeTagNumber other) : this() {
       a_ = other.a_;
       bb_ = other.bb_;
     }
@@ -2552,19 +2511,23 @@
     private static readonly string[] _fieldNames = new string[] { "a", "i" };
     private static readonly uint[] _fieldTags = new uint[] { 10, 16 };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestRecursiveMessage__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[7]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<TestRecursiveMessage> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestRecursiveMessage__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public TestRecursiveMessage() { }
+    public TestRecursiveMessage() {
+      OnConstruction();
+    }
 
-    public TestRecursiveMessage(TestRecursiveMessage other) {
+    partial void OnConstruction();
+
+    public TestRecursiveMessage(TestRecursiveMessage other) : this() {
       A = other.a_ != null ? other.A.Clone() : null;
       i_ = other.i_;
     }
@@ -2697,19 +2660,23 @@
     private static readonly string[] _fieldNames = new string[] { "bb" };
     private static readonly uint[] _fieldTags = new uint[] { 10 };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestMutualRecursionA__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[8]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<TestMutualRecursionA> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestMutualRecursionA__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public TestMutualRecursionA() { }
+    public TestMutualRecursionA() {
+      OnConstruction();
+    }
 
-    public TestMutualRecursionA(TestMutualRecursionA other) {
+    partial void OnConstruction();
+
+    public TestMutualRecursionA(TestMutualRecursionA other) : this() {
       Bb = other.bb_ != null ? other.Bb.Clone() : null;
     }
 
@@ -2815,19 +2782,23 @@
     private static readonly string[] _fieldNames = new string[] { "a", "optional_int32" };
     private static readonly uint[] _fieldTags = new uint[] { 10, 16 };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestMutualRecursionB__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[9]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<TestMutualRecursionB> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestMutualRecursionB__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public TestMutualRecursionB() { }
+    public TestMutualRecursionB() {
+      OnConstruction();
+    }
 
-    public TestMutualRecursionB(TestMutualRecursionB other) {
+    partial void OnConstruction();
+
+    public TestMutualRecursionB(TestMutualRecursionB other) : this() {
       A = other.a_ != null ? other.A.Clone() : null;
       optionalInt32_ = other.optionalInt32_;
     }
@@ -2960,19 +2931,23 @@
     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 pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestCamelCaseFieldNames__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[10]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<TestCamelCaseFieldNames> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestCamelCaseFieldNames__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public TestCamelCaseFieldNames() { }
+    public TestCamelCaseFieldNames() {
+      OnConstruction();
+    }
 
-    public TestCamelCaseFieldNames(TestCamelCaseFieldNames other) {
+    partial void OnConstruction();
+
+    public TestCamelCaseFieldNames(TestCamelCaseFieldNames other) : this() {
       primitiveField_ = other.primitiveField_;
       stringField_ = other.stringField_;
       enumField_ = other.enumField_;
@@ -3236,19 +3211,23 @@
     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 pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestFieldOrderings__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[11]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<TestFieldOrderings> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestFieldOrderings__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public TestFieldOrderings() { }
+    public TestFieldOrderings() {
+      OnConstruction();
+    }
 
-    public TestFieldOrderings(TestFieldOrderings other) {
+    partial void OnConstruction();
+
+    public TestFieldOrderings(TestFieldOrderings other) : this() {
       myString_ = other.myString_;
       myInt_ = other.myInt_;
       myFloat_ = other.myFloat_;
@@ -3436,19 +3415,23 @@
         private static readonly string[] _fieldNames = new string[] { "bb", "oo" };
         private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
         public static pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestFieldOrderings_NestedMessage__Descriptor; }
+          get { return global::Google.Protobuf.TestProtos.TestFieldOrderings.Descriptor.NestedTypes[0]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<NestedMessage> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestFieldOrderings_NestedMessage__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public NestedMessage() { }
+        public NestedMessage() {
+          OnConstruction();
+        }
 
-        public NestedMessage(NestedMessage other) {
+        partial void OnConstruction();
+
+        public NestedMessage(NestedMessage other) : this() {
           oo_ = other.oo_;
           bb_ = other.bb_;
         }
@@ -3579,19 +3562,23 @@
     private static readonly string[] _fieldNames = new string[] { "sparse_enum" };
     private static readonly uint[] _fieldTags = new uint[] { 8 };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_SparseEnumMessage__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[12]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<SparseEnumMessage> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_SparseEnumMessage__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public SparseEnumMessage() { }
+    public SparseEnumMessage() {
+      OnConstruction();
+    }
 
-    public SparseEnumMessage(SparseEnumMessage other) {
+    partial void OnConstruction();
+
+    public SparseEnumMessage(SparseEnumMessage other) : this() {
       sparseEnum_ = other.sparseEnum_;
     }
 
@@ -3690,19 +3677,23 @@
     private static readonly string[] _fieldNames = new string[] { "data" };
     private static readonly uint[] _fieldTags = new uint[] { 10 };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_OneString__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[13]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<OneString> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_OneString__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public OneString() { }
+    public OneString() {
+      OnConstruction();
+    }
 
-    public OneString(OneString other) {
+    partial void OnConstruction();
+
+    public OneString(OneString other) : this() {
       data_ = other.data_;
     }
 
@@ -3801,19 +3792,23 @@
     private static readonly string[] _fieldNames = new string[] { "data" };
     private static readonly uint[] _fieldTags = new uint[] { 10 };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_MoreString__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[14]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<MoreString> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_MoreString__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public MoreString() { }
+    public MoreString() {
+      OnConstruction();
+    }
 
-    public MoreString(MoreString other) {
+    partial void OnConstruction();
+
+    public MoreString(MoreString other) : this() {
       data_ = other.data_.Clone();
     }
 
@@ -3904,19 +3899,23 @@
     private static readonly string[] _fieldNames = new string[] { "data" };
     private static readonly uint[] _fieldTags = new uint[] { 10 };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_OneBytes__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[15]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<OneBytes> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_OneBytes__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public OneBytes() { }
+    public OneBytes() {
+      OnConstruction();
+    }
 
-    public OneBytes(OneBytes other) {
+    partial void OnConstruction();
+
+    public OneBytes(OneBytes other) : this() {
       data_ = other.data_;
     }
 
@@ -4015,19 +4014,23 @@
     private static readonly string[] _fieldNames = new string[] { "data" };
     private static readonly uint[] _fieldTags = new uint[] { 10 };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_MoreBytes__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[16]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<MoreBytes> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_MoreBytes__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public MoreBytes() { }
+    public MoreBytes() {
+      OnConstruction();
+    }
 
-    public MoreBytes(MoreBytes other) {
+    partial void OnConstruction();
+
+    public MoreBytes(MoreBytes other) : this() {
       data_ = other.data_;
     }
 
@@ -4126,19 +4129,23 @@
     private static readonly string[] _fieldNames = new string[] { "data" };
     private static readonly uint[] _fieldTags = new uint[] { 8 };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_Int32Message__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[17]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<Int32Message> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_Int32Message__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public Int32Message() { }
+    public Int32Message() {
+      OnConstruction();
+    }
 
-    public Int32Message(Int32Message other) {
+    partial void OnConstruction();
+
+    public Int32Message(Int32Message other) : this() {
       data_ = other.data_;
     }
 
@@ -4237,19 +4244,23 @@
     private static readonly string[] _fieldNames = new string[] { "data" };
     private static readonly uint[] _fieldTags = new uint[] { 8 };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_Uint32Message__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[18]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<Uint32Message> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_Uint32Message__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public Uint32Message() { }
+    public Uint32Message() {
+      OnConstruction();
+    }
 
-    public Uint32Message(Uint32Message other) {
+    partial void OnConstruction();
+
+    public Uint32Message(Uint32Message other) : this() {
       data_ = other.data_;
     }
 
@@ -4348,19 +4359,23 @@
     private static readonly string[] _fieldNames = new string[] { "data" };
     private static readonly uint[] _fieldTags = new uint[] { 8 };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_Int64Message__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[19]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<Int64Message> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_Int64Message__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public Int64Message() { }
+    public Int64Message() {
+      OnConstruction();
+    }
 
-    public Int64Message(Int64Message other) {
+    partial void OnConstruction();
+
+    public Int64Message(Int64Message other) : this() {
       data_ = other.data_;
     }
 
@@ -4459,19 +4474,23 @@
     private static readonly string[] _fieldNames = new string[] { "data" };
     private static readonly uint[] _fieldTags = new uint[] { 8 };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_Uint64Message__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[20]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<Uint64Message> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_Uint64Message__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public Uint64Message() { }
+    public Uint64Message() {
+      OnConstruction();
+    }
 
-    public Uint64Message(Uint64Message other) {
+    partial void OnConstruction();
+
+    public Uint64Message(Uint64Message other) : this() {
       data_ = other.data_;
     }
 
@@ -4570,19 +4589,23 @@
     private static readonly string[] _fieldNames = new string[] { "data" };
     private static readonly uint[] _fieldTags = new uint[] { 8 };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_BoolMessage__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[21]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<BoolMessage> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_BoolMessage__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public BoolMessage() { }
+    public BoolMessage() {
+      OnConstruction();
+    }
 
-    public BoolMessage(BoolMessage other) {
+    partial void OnConstruction();
+
+    public BoolMessage(BoolMessage other) : this() {
       data_ = other.data_;
     }
 
@@ -4681,19 +4704,23 @@
     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 pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestOneof__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[22]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<TestOneof> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestOneof__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public TestOneof() { }
+    public TestOneof() {
+      OnConstruction();
+    }
 
-    public TestOneof(TestOneof other) {
+    partial void OnConstruction();
+
+    public TestOneof(TestOneof other) : this() {
       switch (other.FooCase) {
         case FooOneofCase.FooInt:
           FooInt = other.FooInt;
@@ -4882,19 +4909,23 @@
     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 pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestPackedTypes__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[23]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<TestPackedTypes> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestPackedTypes__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public TestPackedTypes() { }
+    public TestPackedTypes() {
+      OnConstruction();
+    }
 
-    public TestPackedTypes(TestPackedTypes other) {
+    partial void OnConstruction();
+
+    public TestPackedTypes(TestPackedTypes other) : this() {
       packedInt32_ = other.packedInt32_.Clone();
       packedInt64_ = other.packedInt64_.Clone();
       packedUint32_ = other.packedUint32_.Clone();
@@ -5245,19 +5276,23 @@
     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 pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestUnpackedTypes__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[24]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<TestUnpackedTypes> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestUnpackedTypes__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public TestUnpackedTypes() { }
+    public TestUnpackedTypes() {
+      OnConstruction();
+    }
 
-    public TestUnpackedTypes(TestUnpackedTypes other) {
+    partial void OnConstruction();
+
+    public TestUnpackedTypes(TestUnpackedTypes other) : this() {
       unpackedInt32_ = other.unpackedInt32_.Clone();
       unpackedInt64_ = other.unpackedInt64_.Clone();
       unpackedUint32_ = other.unpackedUint32_.Clone();
@@ -5608,19 +5643,23 @@
     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 pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestRepeatedScalarDifferentTagSizes__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[25]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<TestRepeatedScalarDifferentTagSizes> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestRepeatedScalarDifferentTagSizes__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public TestRepeatedScalarDifferentTagSizes() { }
+    public TestRepeatedScalarDifferentTagSizes() {
+      OnConstruction();
+    }
 
-    public TestRepeatedScalarDifferentTagSizes(TestRepeatedScalarDifferentTagSizes other) {
+    partial void OnConstruction();
+
+    public TestRepeatedScalarDifferentTagSizes(TestRepeatedScalarDifferentTagSizes other) : this() {
       repeatedFixed32_ = other.repeatedFixed32_.Clone();
       repeatedInt32_ = other.repeatedInt32_.Clone();
       repeatedFixed64_ = other.repeatedFixed64_.Clone();
@@ -5812,19 +5851,23 @@
     private static readonly string[] _fieldNames = new string[] { "a" };
     private static readonly uint[] _fieldTags = new uint[] { 10 };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestCommentInjectionMessage__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[26]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<TestCommentInjectionMessage> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestCommentInjectionMessage__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public TestCommentInjectionMessage() { }
+    public TestCommentInjectionMessage() {
+      OnConstruction();
+    }
 
-    public TestCommentInjectionMessage(TestCommentInjectionMessage other) {
+    partial void OnConstruction();
+
+    public TestCommentInjectionMessage(TestCommentInjectionMessage other) : this() {
       a_ = other.a_;
     }
 
@@ -5923,19 +5966,23 @@
     private static readonly string[] _fieldNames = new string[] {  };
     private static readonly uint[] _fieldTags = new uint[] {  };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_FooRequest__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[27]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<FooRequest> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_FooRequest__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public FooRequest() { }
+    public FooRequest() {
+      OnConstruction();
+    }
 
-    public FooRequest(FooRequest other) {
+    partial void OnConstruction();
+
+    public FooRequest(FooRequest other) : this() {
     }
 
     public FooRequest Clone() {
@@ -6007,19 +6054,23 @@
     private static readonly string[] _fieldNames = new string[] {  };
     private static readonly uint[] _fieldTags = new uint[] {  };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_FooResponse__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[28]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<FooResponse> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_FooResponse__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public FooResponse() { }
+    public FooResponse() {
+      OnConstruction();
+    }
 
-    public FooResponse(FooResponse other) {
+    partial void OnConstruction();
+
+    public FooResponse(FooResponse other) : this() {
     }
 
     public FooResponse Clone() {
@@ -6091,19 +6142,23 @@
     private static readonly string[] _fieldNames = new string[] {  };
     private static readonly uint[] _fieldTags = new uint[] {  };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_FooClientMessage__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[29]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<FooClientMessage> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_FooClientMessage__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public FooClientMessage() { }
+    public FooClientMessage() {
+      OnConstruction();
+    }
 
-    public FooClientMessage(FooClientMessage other) {
+    partial void OnConstruction();
+
+    public FooClientMessage(FooClientMessage other) : this() {
     }
 
     public FooClientMessage Clone() {
@@ -6175,19 +6230,23 @@
     private static readonly string[] _fieldNames = new string[] {  };
     private static readonly uint[] _fieldTags = new uint[] {  };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_FooServerMessage__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[30]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<FooServerMessage> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_FooServerMessage__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public FooServerMessage() { }
+    public FooServerMessage() {
+      OnConstruction();
+    }
 
-    public FooServerMessage(FooServerMessage other) {
+    partial void OnConstruction();
+
+    public FooServerMessage(FooServerMessage other) : this() {
     }
 
     public FooServerMessage Clone() {
@@ -6259,19 +6318,23 @@
     private static readonly string[] _fieldNames = new string[] {  };
     private static readonly uint[] _fieldTags = new uint[] {  };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_BarRequest__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[31]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<BarRequest> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_BarRequest__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public BarRequest() { }
+    public BarRequest() {
+      OnConstruction();
+    }
 
-    public BarRequest(BarRequest other) {
+    partial void OnConstruction();
+
+    public BarRequest(BarRequest other) : this() {
     }
 
     public BarRequest Clone() {
@@ -6343,19 +6406,23 @@
     private static readonly string[] _fieldNames = new string[] {  };
     private static readonly uint[] _fieldTags = new uint[] {  };
     public static pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_BarResponse__Descriptor; }
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[32]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<BarResponse> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_BarResponse__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public BarResponse() { }
+    public BarResponse() {
+      OnConstruction();
+    }
 
-    public BarResponse(BarResponse other) {
+    partial void OnConstruction();
+
+    public BarResponse(BarResponse other) : this() {
     }
 
     public BarResponse Clone() {
diff --git a/csharp/src/ProtocolBuffers/Collections/MapField.cs b/csharp/src/ProtocolBuffers/Collections/MapField.cs
index 6d1097a..0f379ea 100644
--- a/csharp/src/ProtocolBuffers/Collections/MapField.cs
+++ b/csharp/src/ProtocolBuffers/Collections/MapField.cs
@@ -48,7 +48,7 @@
     /// </remarks>
     /// <typeparam name="TKey">Key type in the map. Must be a type supported by Protocol Buffer map keys.</typeparam>
     /// <typeparam name="TValue">Value type in the map. Must be a type supported by Protocol Buffers.</typeparam>
-    public sealed class MapField<TKey, TValue> : IDeepCloneable<MapField<TKey, TValue>>, IFreezable, IDictionary<TKey, TValue>, IEquatable<MapField<TKey, TValue>>
+    public sealed class MapField<TKey, TValue> : IDeepCloneable<MapField<TKey, TValue>>, IFreezable, IDictionary<TKey, TValue>, IEquatable<MapField<TKey, TValue>>, IDictionary
     {
         // TODO: Don't create the map/list until we have an entry. (Assume many maps will be empty.)
         private bool frozen;
@@ -64,7 +64,7 @@
             {
                 foreach (var pair in list)
                 {
-                    clone.Add(pair.Key, pair.Value == null ? pair.Value : ((IDeepCloneable<TValue>) pair.Value).Clone());
+                    clone.Add(pair.Key, pair.Value == null ? pair.Value : ((IDeepCloneable<TValue>)pair.Value).Clone());
                 }
             }
             else
@@ -309,7 +309,7 @@
         /// </remarks>
         /// <param name="input">Stream to read from</param>
         /// <param name="codec">Codec describing how the key/value pairs are encoded</param>
-        public void AddEntriesFrom(CodedInputStream input, Codec codec)            
+        public void AddEntriesFrom(CodedInputStream input, Codec codec)
         {
             var adapter = new Codec.MessageAdapter(codec);
             do
@@ -318,7 +318,7 @@
                 input.ReadMessage(adapter);
                 this[adapter.Key] = adapter.Value;
             } while (input.MaybeConsumeTag(codec.MapTag));
-        }        
+        }
 
         public void WriteTo(CodedOutputStream output, Codec codec)
         {
@@ -350,6 +350,104 @@
             return size;
         }
 
+        #region IDictionary explicit interface implementation
+        void IDictionary.Add(object key, object value)
+        {
+            Add((TKey)key, (TValue)value);
+        }
+
+        bool IDictionary.Contains(object key)
+        {
+            if (!(key is TKey))
+            {
+                return false;
+            }
+            return ContainsKey((TKey)key);
+        }
+
+        IDictionaryEnumerator IDictionary.GetEnumerator()
+        {
+            return new DictionaryEnumerator(GetEnumerator());
+        }
+
+        void IDictionary.Remove(object key)
+        {
+            ThrowHelper.ThrowIfNull(key, "key");
+            this.CheckMutable();
+            if (!(key is TKey))
+            {
+                return;
+            }
+            Remove((TKey)key);
+        }
+
+        void ICollection.CopyTo(Array array, int index)
+        {
+            // This is ugly and slow as heck, but with any luck it will never be used anyway.
+            ICollection temp = this.Select(pair => new DictionaryEntry(pair.Key, pair.Value)).ToList();
+            temp.CopyTo(array, index);
+        }
+
+        bool IDictionary.IsFixedSize { get { return IsFrozen; } }
+
+        ICollection IDictionary.Keys { get { return (ICollection)Keys; } }
+
+        ICollection IDictionary.Values { get { return (ICollection)Values; } }
+
+        bool ICollection.IsSynchronized { get { return false; } }
+
+        object ICollection.SyncRoot { get { return this; } }
+
+        object IDictionary.this[object key]
+        {
+            get
+            {
+                ThrowHelper.ThrowIfNull(key, "key");
+                if (!(key is TKey))
+                {
+                    return null;
+                }
+                TValue value;
+                TryGetValue((TKey)key, out value);
+                return value;
+            }
+
+            set
+            {
+                if (frozen)
+                {
+                    throw new NotSupportedException("Dictionary is frozen");
+                }
+                this[(TKey)key] = (TValue)value;
+            }
+        }
+        #endregion
+
+        private class DictionaryEnumerator : IDictionaryEnumerator
+        {
+            private readonly IEnumerator<KeyValuePair<TKey, TValue>> enumerator;
+
+            internal DictionaryEnumerator(IEnumerator<KeyValuePair<TKey, TValue>> enumerator)
+            {
+                this.enumerator = enumerator;
+            }
+
+            public bool MoveNext()
+            {
+                return enumerator.MoveNext();
+            }
+
+            public void Reset()
+            {
+                enumerator.Reset();
+            }
+
+            public object Current { get { return Entry; } }
+            public DictionaryEntry Entry { get { return new DictionaryEntry(Key, Value); } }
+            public object Key { get { return enumerator.Current.Key; } }
+            public object Value { get { return enumerator.Current.Value; } }
+        }
+
         /// <summary>
         /// A codec for a specific map field. This contains all the information required to encoded and
         /// decode the nested messages.
diff --git a/csharp/src/ProtocolBuffers/Collections/RepeatedField.cs b/csharp/src/ProtocolBuffers/Collections/RepeatedField.cs
index ed31149..b6b52cb 100644
--- a/csharp/src/ProtocolBuffers/Collections/RepeatedField.cs
+++ b/csharp/src/ProtocolBuffers/Collections/RepeatedField.cs
@@ -41,7 +41,7 @@
     /// restrictions (no null values) and capabilities (deep cloning and freezing).
     /// </summary>
     /// <typeparam name="T">The element type of the repeated field.</typeparam>
-    public sealed class RepeatedField<T> : IList<T>, IDeepCloneable<RepeatedField<T>>, IEquatable<RepeatedField<T>>, IFreezable
+    public sealed class RepeatedField<T> : IList<T>, IList, IDeepCloneable<RepeatedField<T>>, IEquatable<RepeatedField<T>>, IFreezable
     {
         private static readonly T[] EmptyArray = new T[0];
 
@@ -376,6 +376,7 @@
             this.CheckMutable();
             EnsureSize(count + 1);
             Array.Copy(array, index, array, index + 1, count - index);
+            array[index] = item;
             count++;
         }
 
@@ -415,7 +416,60 @@
                 array[index] = value;
             }
         }
-        
+
+        #region Explicit interface implementation for IList and ICollection.
+        bool IList.IsFixedSize { get { return IsFrozen; } }
+
+        void ICollection.CopyTo(Array array, int index)
+        {
+            Array.Copy(this.array, 0, array, index, count);
+        }
+
+        bool ICollection.IsSynchronized { get { return false; } }
+
+        object ICollection.SyncRoot { get { return this; } }
+
+        object IList.this[int index]
+        {
+            get { return this[index]; }
+            set { this[index] = (T)value; }
+        }
+
+        int IList.Add(object value)
+        {
+            Add((T) value);
+            return count - 1;
+        }
+
+        bool IList.Contains(object value)
+        {
+            return (value is T && Contains((T)value));
+        }
+
+        int IList.IndexOf(object value)
+        {
+            if (!(value is T))
+            {
+                return -1;
+            }
+            return IndexOf((T)value);
+        }
+
+        void IList.Insert(int index, object value)
+        {
+            Insert(index, (T) value);
+        }
+
+        void IList.Remove(object value)
+        {
+            if (!(value is T))
+            {
+                return;
+            }
+            Remove((T)value);
+        }
+        #endregion
+
         public struct Enumerator : IEnumerator<T>
         {
             private int index;
@@ -431,6 +485,7 @@
             {
                 if (index + 1 >= field.Count)
                 {
+                    index = field.Count;
                     return false;
                 }
                 index++;
diff --git a/csharp/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs b/csharp/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs
index 80166a3..c87b367 100644
--- a/csharp/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs
+++ b/csharp/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs
@@ -10,53 +10,31 @@
 namespace Google.Protobuf.DescriptorProtos {
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public static partial class DescriptorProtoFile {
+  internal static partial class DescriptorProtoFile {
 
     #region Static variables
-    internal static pbd::MessageDescriptor internal__static_google_protobuf_FileDescriptorSet__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.FileDescriptorSet> internal__static_google_protobuf_FileDescriptorSet__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_google_protobuf_FileDescriptorProto__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.FileDescriptorProto> internal__static_google_protobuf_FileDescriptorProto__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_google_protobuf_DescriptorProto__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.DescriptorProto> internal__static_google_protobuf_DescriptorProto__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_google_protobuf_DescriptorProto_ExtensionRange__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ExtensionRange> internal__static_google_protobuf_DescriptorProto_ExtensionRange__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_google_protobuf_DescriptorProto_ReservedRange__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ReservedRange> internal__static_google_protobuf_DescriptorProto_ReservedRange__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_google_protobuf_FieldDescriptorProto__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto> internal__static_google_protobuf_FieldDescriptorProto__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_google_protobuf_OneofDescriptorProto__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.OneofDescriptorProto> internal__static_google_protobuf_OneofDescriptorProto__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_google_protobuf_EnumDescriptorProto__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.EnumDescriptorProto> internal__static_google_protobuf_EnumDescriptorProto__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_google_protobuf_EnumValueDescriptorProto__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.EnumValueDescriptorProto> internal__static_google_protobuf_EnumValueDescriptorProto__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_google_protobuf_ServiceDescriptorProto__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.ServiceDescriptorProto> internal__static_google_protobuf_ServiceDescriptorProto__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_google_protobuf_MethodDescriptorProto__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.MethodDescriptorProto> internal__static_google_protobuf_MethodDescriptorProto__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_google_protobuf_FileOptions__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.FileOptions> internal__static_google_protobuf_FileOptions__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_google_protobuf_MessageOptions__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.MessageOptions> internal__static_google_protobuf_MessageOptions__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_google_protobuf_FieldOptions__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.FieldOptions> internal__static_google_protobuf_FieldOptions__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_google_protobuf_EnumOptions__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.EnumOptions> internal__static_google_protobuf_EnumOptions__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_google_protobuf_EnumValueOptions__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.EnumValueOptions> internal__static_google_protobuf_EnumValueOptions__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_google_protobuf_ServiceOptions__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.ServiceOptions> internal__static_google_protobuf_ServiceOptions__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_google_protobuf_MethodOptions__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.MethodOptions> internal__static_google_protobuf_MethodOptions__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_google_protobuf_UninterpretedOption__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> internal__static_google_protobuf_UninterpretedOption__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_google_protobuf_UninterpretedOption_NamePart__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Types.NamePart> internal__static_google_protobuf_UninterpretedOption_NamePart__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_google_protobuf_SourceCodeInfo__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.SourceCodeInfo> internal__static_google_protobuf_SourceCodeInfo__FieldAccessorTable;
-    internal static pbd::MessageDescriptor internal__static_google_protobuf_SourceCodeInfo_Location__Descriptor;
-    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.SourceCodeInfo.Types.Location> internal__static_google_protobuf_SourceCodeInfo_Location__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_google_protobuf_FileDescriptorSet__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_google_protobuf_FileDescriptorProto__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_google_protobuf_DescriptorProto__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_google_protobuf_DescriptorProto_ExtensionRange__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_google_protobuf_DescriptorProto_ReservedRange__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_google_protobuf_FieldDescriptorProto__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_google_protobuf_OneofDescriptorProto__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_google_protobuf_EnumDescriptorProto__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_google_protobuf_EnumValueDescriptorProto__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_google_protobuf_ServiceDescriptorProto__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_google_protobuf_MethodDescriptorProto__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_google_protobuf_FileOptions__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_google_protobuf_MessageOptions__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_google_protobuf_FieldOptions__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_google_protobuf_EnumOptions__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_google_protobuf_EnumValueOptions__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_google_protobuf_ServiceOptions__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_google_protobuf_MethodOptions__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_google_protobuf_UninterpretedOption__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_google_protobuf_UninterpretedOption_NamePart__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_google_protobuf_SourceCodeInfo__FieldAccessorTable;
+    internal static pb::FieldAccess.FieldAccessorTable internal__static_google_protobuf_SourceCodeInfo_Location__FieldAccessorTable;
     #endregion
     #region Descriptor
     public static pbd::FileDescriptor Descriptor {
@@ -178,126 +156,105 @@
             "bWVudHMYBiADKAlCXgoTY29tLmdvb2dsZS5wcm90b2J1ZkIQRGVzY3JpcHRv", 
             "clByb3Rvc0gBWgpkZXNjcmlwdG9yogIDR1BCqgIgR29vZ2xlLlByb3RvYnVm", 
           "LkRlc2NyaXB0b3JQcm90b3M="));
-      pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {
-        descriptor = root;
-        internal__static_google_protobuf_FileDescriptorSet__Descriptor = Descriptor.MessageTypes[0];
-        internal__static_google_protobuf_FileDescriptorSet__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.FileDescriptorSet>(internal__static_google_protobuf_FileDescriptorSet__Descriptor,
-                new string[] { "File", });
-        internal__static_google_protobuf_FileDescriptorProto__Descriptor = Descriptor.MessageTypes[1];
-        internal__static_google_protobuf_FileDescriptorProto__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.FileDescriptorProto>(internal__static_google_protobuf_FileDescriptorProto__Descriptor,
-                new string[] { "Name", "Package", "Dependency", "PublicDependency", "WeakDependency", "MessageType", "EnumType", "Service", "Extension", "Options", "SourceCodeInfo", "Syntax", });
-        internal__static_google_protobuf_DescriptorProto__Descriptor = Descriptor.MessageTypes[2];
-        internal__static_google_protobuf_DescriptorProto__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.DescriptorProto>(internal__static_google_protobuf_DescriptorProto__Descriptor,
-                new string[] { "Name", "Field", "Extension", "NestedType", "EnumType", "ExtensionRange", "OneofDecl", "Options", "ReservedRange", "ReservedName", });
-        internal__static_google_protobuf_DescriptorProto_ExtensionRange__Descriptor = internal__static_google_protobuf_DescriptorProto__Descriptor.NestedTypes[0];
-        internal__static_google_protobuf_DescriptorProto_ExtensionRange__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ExtensionRange>(internal__static_google_protobuf_DescriptorProto_ExtensionRange__Descriptor,
-                new string[] { "Start", "End", });
-        internal__static_google_protobuf_DescriptorProto_ReservedRange__Descriptor = internal__static_google_protobuf_DescriptorProto__Descriptor.NestedTypes[1];
-        internal__static_google_protobuf_DescriptorProto_ReservedRange__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ReservedRange>(internal__static_google_protobuf_DescriptorProto_ReservedRange__Descriptor,
-                new string[] { "Start", "End", });
-        internal__static_google_protobuf_FieldDescriptorProto__Descriptor = Descriptor.MessageTypes[3];
-        internal__static_google_protobuf_FieldDescriptorProto__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto>(internal__static_google_protobuf_FieldDescriptorProto__Descriptor,
-                new string[] { "Name", "Number", "Label", "Type", "TypeName", "Extendee", "DefaultValue", "OneofIndex", "Options", });
-        internal__static_google_protobuf_OneofDescriptorProto__Descriptor = Descriptor.MessageTypes[4];
-        internal__static_google_protobuf_OneofDescriptorProto__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.OneofDescriptorProto>(internal__static_google_protobuf_OneofDescriptorProto__Descriptor,
-                new string[] { "Name", });
-        internal__static_google_protobuf_EnumDescriptorProto__Descriptor = Descriptor.MessageTypes[5];
-        internal__static_google_protobuf_EnumDescriptorProto__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.EnumDescriptorProto>(internal__static_google_protobuf_EnumDescriptorProto__Descriptor,
-                new string[] { "Name", "Value", "Options", });
-        internal__static_google_protobuf_EnumValueDescriptorProto__Descriptor = Descriptor.MessageTypes[6];
-        internal__static_google_protobuf_EnumValueDescriptorProto__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.EnumValueDescriptorProto>(internal__static_google_protobuf_EnumValueDescriptorProto__Descriptor,
-                new string[] { "Name", "Number", "Options", });
-        internal__static_google_protobuf_ServiceDescriptorProto__Descriptor = Descriptor.MessageTypes[7];
-        internal__static_google_protobuf_ServiceDescriptorProto__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.ServiceDescriptorProto>(internal__static_google_protobuf_ServiceDescriptorProto__Descriptor,
-                new string[] { "Name", "Method", "Options", });
-        internal__static_google_protobuf_MethodDescriptorProto__Descriptor = Descriptor.MessageTypes[8];
-        internal__static_google_protobuf_MethodDescriptorProto__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.MethodDescriptorProto>(internal__static_google_protobuf_MethodDescriptorProto__Descriptor,
-                new string[] { "Name", "InputType", "OutputType", "Options", "ClientStreaming", "ServerStreaming", });
-        internal__static_google_protobuf_FileOptions__Descriptor = Descriptor.MessageTypes[9];
-        internal__static_google_protobuf_FileOptions__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.FileOptions>(internal__static_google_protobuf_FileOptions__Descriptor,
-                new string[] { "JavaPackage", "JavaOuterClassname", "JavaMultipleFiles", "JavaGenerateEqualsAndHash", "JavaStringCheckUtf8", "OptimizeFor", "GoPackage", "CcGenericServices", "JavaGenericServices", "PyGenericServices", "Deprecated", "CcEnableArenas", "ObjcClassPrefix", "CsharpNamespace", "UninterpretedOption", });
-        internal__static_google_protobuf_MessageOptions__Descriptor = Descriptor.MessageTypes[10];
-        internal__static_google_protobuf_MessageOptions__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.MessageOptions>(internal__static_google_protobuf_MessageOptions__Descriptor,
-                new string[] { "MessageSetWireFormat", "NoStandardDescriptorAccessor", "Deprecated", "MapEntry", "UninterpretedOption", });
-        internal__static_google_protobuf_FieldOptions__Descriptor = Descriptor.MessageTypes[11];
-        internal__static_google_protobuf_FieldOptions__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.FieldOptions>(internal__static_google_protobuf_FieldOptions__Descriptor,
-                new string[] { "Ctype", "Packed", "Jstype", "Lazy", "Deprecated", "Weak", "UninterpretedOption", });
-        internal__static_google_protobuf_EnumOptions__Descriptor = Descriptor.MessageTypes[12];
-        internal__static_google_protobuf_EnumOptions__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.EnumOptions>(internal__static_google_protobuf_EnumOptions__Descriptor,
-                new string[] { "AllowAlias", "Deprecated", "UninterpretedOption", });
-        internal__static_google_protobuf_EnumValueOptions__Descriptor = Descriptor.MessageTypes[13];
-        internal__static_google_protobuf_EnumValueOptions__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.EnumValueOptions>(internal__static_google_protobuf_EnumValueOptions__Descriptor,
-                new string[] { "Deprecated", "UninterpretedOption", });
-        internal__static_google_protobuf_ServiceOptions__Descriptor = Descriptor.MessageTypes[14];
-        internal__static_google_protobuf_ServiceOptions__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.ServiceOptions>(internal__static_google_protobuf_ServiceOptions__Descriptor,
-                new string[] { "Deprecated", "UninterpretedOption", });
-        internal__static_google_protobuf_MethodOptions__Descriptor = Descriptor.MessageTypes[15];
-        internal__static_google_protobuf_MethodOptions__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.MethodOptions>(internal__static_google_protobuf_MethodOptions__Descriptor,
-                new string[] { "Deprecated", "UninterpretedOption", });
-        internal__static_google_protobuf_UninterpretedOption__Descriptor = Descriptor.MessageTypes[16];
-        internal__static_google_protobuf_UninterpretedOption__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.UninterpretedOption>(internal__static_google_protobuf_UninterpretedOption__Descriptor,
-                new string[] { "Name", "IdentifierValue", "PositiveIntValue", "NegativeIntValue", "DoubleValue", "StringValue", "AggregateValue", });
-        internal__static_google_protobuf_UninterpretedOption_NamePart__Descriptor = internal__static_google_protobuf_UninterpretedOption__Descriptor.NestedTypes[0];
-        internal__static_google_protobuf_UninterpretedOption_NamePart__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Types.NamePart>(internal__static_google_protobuf_UninterpretedOption_NamePart__Descriptor,
-                new string[] { "NamePart_", "IsExtension", });
-        internal__static_google_protobuf_SourceCodeInfo__Descriptor = Descriptor.MessageTypes[17];
-        internal__static_google_protobuf_SourceCodeInfo__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.SourceCodeInfo>(internal__static_google_protobuf_SourceCodeInfo__Descriptor,
-                new string[] { "Location", });
-        internal__static_google_protobuf_SourceCodeInfo_Location__Descriptor = internal__static_google_protobuf_SourceCodeInfo__Descriptor.NestedTypes[0];
-        internal__static_google_protobuf_SourceCodeInfo_Location__FieldAccessorTable = 
-            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.DescriptorProtos.SourceCodeInfo.Types.Location>(internal__static_google_protobuf_SourceCodeInfo_Location__Descriptor,
-                new string[] { "Path", "Span", "LeadingComments", "TrailingComments", "LeadingDetachedComments", });
-      };
-      pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
+      descriptor = pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
           new pbd::FileDescriptor[] {
-          }, assigner);
+          });
+      internal__static_google_protobuf_FileDescriptorSet__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.DescriptorProtos.FileDescriptorSet), descriptor.MessageTypes[0],
+              new string[] { "File", });
+      internal__static_google_protobuf_FileDescriptorProto__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.DescriptorProtos.FileDescriptorProto), descriptor.MessageTypes[1],
+              new string[] { "Name", "Package", "Dependency", "PublicDependency", "WeakDependency", "MessageType", "EnumType", "Service", "Extension", "Options", "SourceCodeInfo", "Syntax", });
+      internal__static_google_protobuf_DescriptorProto__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.DescriptorProtos.DescriptorProto), descriptor.MessageTypes[2],
+              new string[] { "Name", "Field", "Extension", "NestedType", "EnumType", "ExtensionRange", "OneofDecl", "Options", "ReservedRange", "ReservedName", });
+      internal__static_google_protobuf_DescriptorProto_ExtensionRange__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ExtensionRange), descriptor.MessageTypes[2].NestedTypes[0],
+              new string[] { "Start", "End", });
+      internal__static_google_protobuf_DescriptorProto_ReservedRange__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ReservedRange), descriptor.MessageTypes[2].NestedTypes[1],
+              new string[] { "Start", "End", });
+      internal__static_google_protobuf_FieldDescriptorProto__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto), descriptor.MessageTypes[3],
+              new string[] { "Name", "Number", "Label", "Type", "TypeName", "Extendee", "DefaultValue", "OneofIndex", "Options", });
+      internal__static_google_protobuf_OneofDescriptorProto__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.DescriptorProtos.OneofDescriptorProto), descriptor.MessageTypes[4],
+              new string[] { "Name", });
+      internal__static_google_protobuf_EnumDescriptorProto__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.DescriptorProtos.EnumDescriptorProto), descriptor.MessageTypes[5],
+              new string[] { "Name", "Value", "Options", });
+      internal__static_google_protobuf_EnumValueDescriptorProto__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.DescriptorProtos.EnumValueDescriptorProto), descriptor.MessageTypes[6],
+              new string[] { "Name", "Number", "Options", });
+      internal__static_google_protobuf_ServiceDescriptorProto__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.DescriptorProtos.ServiceDescriptorProto), descriptor.MessageTypes[7],
+              new string[] { "Name", "Method", "Options", });
+      internal__static_google_protobuf_MethodDescriptorProto__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.DescriptorProtos.MethodDescriptorProto), descriptor.MessageTypes[8],
+              new string[] { "Name", "InputType", "OutputType", "Options", "ClientStreaming", "ServerStreaming", });
+      internal__static_google_protobuf_FileOptions__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.DescriptorProtos.FileOptions), descriptor.MessageTypes[9],
+              new string[] { "JavaPackage", "JavaOuterClassname", "JavaMultipleFiles", "JavaGenerateEqualsAndHash", "JavaStringCheckUtf8", "OptimizeFor", "GoPackage", "CcGenericServices", "JavaGenericServices", "PyGenericServices", "Deprecated", "CcEnableArenas", "ObjcClassPrefix", "CsharpNamespace", "UninterpretedOption", });
+      internal__static_google_protobuf_MessageOptions__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.DescriptorProtos.MessageOptions), descriptor.MessageTypes[10],
+              new string[] { "MessageSetWireFormat", "NoStandardDescriptorAccessor", "Deprecated", "MapEntry", "UninterpretedOption", });
+      internal__static_google_protobuf_FieldOptions__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.DescriptorProtos.FieldOptions), descriptor.MessageTypes[11],
+              new string[] { "Ctype", "Packed", "Jstype", "Lazy", "Deprecated", "Weak", "UninterpretedOption", });
+      internal__static_google_protobuf_EnumOptions__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.DescriptorProtos.EnumOptions), descriptor.MessageTypes[12],
+              new string[] { "AllowAlias", "Deprecated", "UninterpretedOption", });
+      internal__static_google_protobuf_EnumValueOptions__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.DescriptorProtos.EnumValueOptions), descriptor.MessageTypes[13],
+              new string[] { "Deprecated", "UninterpretedOption", });
+      internal__static_google_protobuf_ServiceOptions__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.DescriptorProtos.ServiceOptions), descriptor.MessageTypes[14],
+              new string[] { "Deprecated", "UninterpretedOption", });
+      internal__static_google_protobuf_MethodOptions__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.DescriptorProtos.MethodOptions), descriptor.MessageTypes[15],
+              new string[] { "Deprecated", "UninterpretedOption", });
+      internal__static_google_protobuf_UninterpretedOption__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.DescriptorProtos.UninterpretedOption), descriptor.MessageTypes[16],
+              new string[] { "Name", "IdentifierValue", "PositiveIntValue", "NegativeIntValue", "DoubleValue", "StringValue", "AggregateValue", });
+      internal__static_google_protobuf_UninterpretedOption_NamePart__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Types.NamePart), descriptor.MessageTypes[16].NestedTypes[0],
+              new string[] { "NamePart_", "IsExtension", });
+      internal__static_google_protobuf_SourceCodeInfo__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.DescriptorProtos.SourceCodeInfo), descriptor.MessageTypes[17],
+              new string[] { "Location", });
+      internal__static_google_protobuf_SourceCodeInfo_Location__FieldAccessorTable = 
+          new pb::FieldAccess.FieldAccessorTable(typeof(global::Google.Protobuf.DescriptorProtos.SourceCodeInfo.Types.Location), descriptor.MessageTypes[17].NestedTypes[0],
+              new string[] { "Path", "Span", "LeadingComments", "TrailingComments", "LeadingDetachedComments", });
     }
     #endregion
 
   }
   #region Messages
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class FileDescriptorSet : pb::IMessage<FileDescriptorSet> {
+  internal sealed partial class FileDescriptorSet : pb::IMessage<FileDescriptorSet> {
     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 pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_FileDescriptorSet__Descriptor; }
+      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.Descriptor.MessageTypes[0]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<FileDescriptorSet> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_FileDescriptorSet__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public FileDescriptorSet() { }
+    public FileDescriptorSet() {
+      OnConstruction();
+    }
 
-    public FileDescriptorSet(FileDescriptorSet other) {
+    partial void OnConstruction();
+
+    public FileDescriptorSet(FileDescriptorSet other) : this() {
       file_ = other.file_.Clone();
     }
 
@@ -317,7 +274,7 @@
     private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.FileDescriptorProto> _repeated_file_codec
         = pb::FieldCodec.ForMessage(10, global::Google.Protobuf.DescriptorProtos.FileDescriptorProto.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FileDescriptorProto> file_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FileDescriptorProto>();
-    public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FileDescriptorProto> File {
+    internal pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FileDescriptorProto> File {
       get { return file_; }
     }
 
@@ -381,26 +338,30 @@
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class FileDescriptorProto : pb::IMessage<FileDescriptorProto> {
+  internal sealed partial class FileDescriptorProto : pb::IMessage<FileDescriptorProto> {
     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 pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_FileDescriptorProto__Descriptor; }
+      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.Descriptor.MessageTypes[1]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<FileDescriptorProto> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_FileDescriptorProto__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public FileDescriptorProto() { }
+    public FileDescriptorProto() {
+      OnConstruction();
+    }
 
-    public FileDescriptorProto(FileDescriptorProto other) {
+    partial void OnConstruction();
+
+    public FileDescriptorProto(FileDescriptorProto other) : this() {
       name_ = other.name_;
       package_ = other.package_;
       dependency_ = other.dependency_.Clone();
@@ -437,7 +398,7 @@
 
     public const int NameFieldNumber = 1;
     private string name_ = "";
-    public string Name {
+    internal string Name {
       get { return name_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -447,7 +408,7 @@
 
     public const int PackageFieldNumber = 2;
     private string package_ = "";
-    public string Package {
+    internal string Package {
       get { return package_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -459,7 +420,7 @@
     private static readonly pb::FieldCodec<string> _repeated_dependency_codec
         = pb::FieldCodec.ForString(26);
     private readonly pbc::RepeatedField<string> dependency_ = new pbc::RepeatedField<string>();
-    public pbc::RepeatedField<string> Dependency {
+    internal pbc::RepeatedField<string> Dependency {
       get { return dependency_; }
     }
 
@@ -467,7 +428,7 @@
     private static readonly pb::FieldCodec<int> _repeated_publicDependency_codec
         = pb::FieldCodec.ForInt32(80);
     private readonly pbc::RepeatedField<int> publicDependency_ = new pbc::RepeatedField<int>();
-    public pbc::RepeatedField<int> PublicDependency {
+    internal pbc::RepeatedField<int> PublicDependency {
       get { return publicDependency_; }
     }
 
@@ -475,7 +436,7 @@
     private static readonly pb::FieldCodec<int> _repeated_weakDependency_codec
         = pb::FieldCodec.ForInt32(88);
     private readonly pbc::RepeatedField<int> weakDependency_ = new pbc::RepeatedField<int>();
-    public pbc::RepeatedField<int> WeakDependency {
+    internal pbc::RepeatedField<int> WeakDependency {
       get { return weakDependency_; }
     }
 
@@ -483,7 +444,7 @@
     private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.DescriptorProto> _repeated_messageType_codec
         = pb::FieldCodec.ForMessage(34, global::Google.Protobuf.DescriptorProtos.DescriptorProto.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.DescriptorProto> messageType_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.DescriptorProto>();
-    public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.DescriptorProto> MessageType {
+    internal pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.DescriptorProto> MessageType {
       get { return messageType_; }
     }
 
@@ -491,7 +452,7 @@
     private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.EnumDescriptorProto> _repeated_enumType_codec
         = pb::FieldCodec.ForMessage(42, global::Google.Protobuf.DescriptorProtos.EnumDescriptorProto.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.EnumDescriptorProto> enumType_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.EnumDescriptorProto>();
-    public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.EnumDescriptorProto> EnumType {
+    internal pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.EnumDescriptorProto> EnumType {
       get { return enumType_; }
     }
 
@@ -499,7 +460,7 @@
     private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.ServiceDescriptorProto> _repeated_service_codec
         = pb::FieldCodec.ForMessage(50, global::Google.Protobuf.DescriptorProtos.ServiceDescriptorProto.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.ServiceDescriptorProto> service_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.ServiceDescriptorProto>();
-    public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.ServiceDescriptorProto> Service {
+    internal pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.ServiceDescriptorProto> Service {
       get { return service_; }
     }
 
@@ -507,13 +468,13 @@
     private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto> _repeated_extension_codec
         = pb::FieldCodec.ForMessage(58, global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto> extension_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto>();
-    public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto> Extension {
+    internal pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto> Extension {
       get { return extension_; }
     }
 
     public const int OptionsFieldNumber = 8;
     private global::Google.Protobuf.DescriptorProtos.FileOptions options_;
-    public global::Google.Protobuf.DescriptorProtos.FileOptions Options {
+    internal global::Google.Protobuf.DescriptorProtos.FileOptions Options {
       get { return options_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -523,7 +484,7 @@
 
     public const int SourceCodeInfoFieldNumber = 9;
     private global::Google.Protobuf.DescriptorProtos.SourceCodeInfo sourceCodeInfo_;
-    public global::Google.Protobuf.DescriptorProtos.SourceCodeInfo SourceCodeInfo {
+    internal global::Google.Protobuf.DescriptorProtos.SourceCodeInfo SourceCodeInfo {
       get { return sourceCodeInfo_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -533,7 +494,7 @@
 
     public const int SyntaxFieldNumber = 12;
     private string syntax_ = "";
-    public string Syntax {
+    internal string Syntax {
       get { return syntax_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -749,26 +710,30 @@
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class DescriptorProto : pb::IMessage<DescriptorProto> {
+  internal sealed partial class DescriptorProto : pb::IMessage<DescriptorProto> {
     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 pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_DescriptorProto__Descriptor; }
+      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.Descriptor.MessageTypes[2]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<DescriptorProto> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_DescriptorProto__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public DescriptorProto() { }
+    public DescriptorProto() {
+      OnConstruction();
+    }
 
-    public DescriptorProto(DescriptorProto other) {
+    partial void OnConstruction();
+
+    public DescriptorProto(DescriptorProto other) : this() {
       name_ = other.name_;
       field_ = other.field_.Clone();
       extension_ = other.extension_.Clone();
@@ -803,7 +768,7 @@
 
     public const int NameFieldNumber = 1;
     private string name_ = "";
-    public string Name {
+    internal string Name {
       get { return name_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -815,7 +780,7 @@
     private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto> _repeated_field_codec
         = pb::FieldCodec.ForMessage(18, global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto> field_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto>();
-    public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto> Field {
+    internal pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto> Field {
       get { return field_; }
     }
 
@@ -823,7 +788,7 @@
     private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto> _repeated_extension_codec
         = pb::FieldCodec.ForMessage(50, global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto> extension_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto>();
-    public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto> Extension {
+    internal pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto> Extension {
       get { return extension_; }
     }
 
@@ -831,7 +796,7 @@
     private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.DescriptorProto> _repeated_nestedType_codec
         = pb::FieldCodec.ForMessage(26, global::Google.Protobuf.DescriptorProtos.DescriptorProto.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.DescriptorProto> nestedType_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.DescriptorProto>();
-    public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.DescriptorProto> NestedType {
+    internal pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.DescriptorProto> NestedType {
       get { return nestedType_; }
     }
 
@@ -839,7 +804,7 @@
     private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.EnumDescriptorProto> _repeated_enumType_codec
         = pb::FieldCodec.ForMessage(34, global::Google.Protobuf.DescriptorProtos.EnumDescriptorProto.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.EnumDescriptorProto> enumType_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.EnumDescriptorProto>();
-    public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.EnumDescriptorProto> EnumType {
+    internal pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.EnumDescriptorProto> EnumType {
       get { return enumType_; }
     }
 
@@ -847,7 +812,7 @@
     private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ExtensionRange> _repeated_extensionRange_codec
         = pb::FieldCodec.ForMessage(42, global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ExtensionRange.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ExtensionRange> extensionRange_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ExtensionRange>();
-    public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ExtensionRange> ExtensionRange {
+    internal pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ExtensionRange> ExtensionRange {
       get { return extensionRange_; }
     }
 
@@ -855,13 +820,13 @@
     private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.OneofDescriptorProto> _repeated_oneofDecl_codec
         = pb::FieldCodec.ForMessage(66, global::Google.Protobuf.DescriptorProtos.OneofDescriptorProto.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.OneofDescriptorProto> oneofDecl_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.OneofDescriptorProto>();
-    public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.OneofDescriptorProto> OneofDecl {
+    internal pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.OneofDescriptorProto> OneofDecl {
       get { return oneofDecl_; }
     }
 
     public const int OptionsFieldNumber = 7;
     private global::Google.Protobuf.DescriptorProtos.MessageOptions options_;
-    public global::Google.Protobuf.DescriptorProtos.MessageOptions Options {
+    internal global::Google.Protobuf.DescriptorProtos.MessageOptions Options {
       get { return options_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -873,7 +838,7 @@
     private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ReservedRange> _repeated_reservedRange_codec
         = pb::FieldCodec.ForMessage(74, global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ReservedRange.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ReservedRange> reservedRange_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ReservedRange>();
-    public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ReservedRange> ReservedRange {
+    internal pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ReservedRange> ReservedRange {
       get { return reservedRange_; }
     }
 
@@ -881,7 +846,7 @@
     private static readonly pb::FieldCodec<string> _repeated_reservedName_codec
         = pb::FieldCodec.ForString(82);
     private readonly pbc::RepeatedField<string> reservedName_ = new pbc::RepeatedField<string>();
-    public pbc::RepeatedField<string> ReservedName {
+    internal pbc::RepeatedField<string> ReservedName {
       get { return reservedName_; }
     }
 
@@ -1047,26 +1012,30 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
     public static partial class Types {
       [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-      public sealed partial class ExtensionRange : pb::IMessage<ExtensionRange> {
+      internal sealed partial class ExtensionRange : pb::IMessage<ExtensionRange> {
         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 pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_DescriptorProto_ExtensionRange__Descriptor; }
+          get { return global::Google.Protobuf.DescriptorProtos.DescriptorProto.Descriptor.NestedTypes[0]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<ExtensionRange> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_DescriptorProto_ExtensionRange__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public ExtensionRange() { }
+        public ExtensionRange() {
+          OnConstruction();
+        }
 
-        public ExtensionRange(ExtensionRange other) {
+        partial void OnConstruction();
+
+        public ExtensionRange(ExtensionRange other) : this() {
           start_ = other.start_;
           end_ = other.end_;
         }
@@ -1084,7 +1053,7 @@
 
         public const int StartFieldNumber = 1;
         private int start_;
-        public int Start {
+        internal int Start {
           get { return start_; }
           set {
             pb::Freezable.CheckMutable(this);
@@ -1094,7 +1063,7 @@
 
         public const int EndFieldNumber = 2;
         private int end_;
-        public int End {
+        internal int End {
           get { return end_; }
           set {
             pb::Freezable.CheckMutable(this);
@@ -1185,26 +1154,30 @@
       }
 
       [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-      public sealed partial class ReservedRange : pb::IMessage<ReservedRange> {
+      internal sealed partial class ReservedRange : pb::IMessage<ReservedRange> {
         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 pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_DescriptorProto_ReservedRange__Descriptor; }
+          get { return global::Google.Protobuf.DescriptorProtos.DescriptorProto.Descriptor.NestedTypes[1]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<ReservedRange> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_DescriptorProto_ReservedRange__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public ReservedRange() { }
+        public ReservedRange() {
+          OnConstruction();
+        }
 
-        public ReservedRange(ReservedRange other) {
+        partial void OnConstruction();
+
+        public ReservedRange(ReservedRange other) : this() {
           start_ = other.start_;
           end_ = other.end_;
         }
@@ -1222,7 +1195,7 @@
 
         public const int StartFieldNumber = 1;
         private int start_;
-        public int Start {
+        internal int Start {
           get { return start_; }
           set {
             pb::Freezable.CheckMutable(this);
@@ -1232,7 +1205,7 @@
 
         public const int EndFieldNumber = 2;
         private int end_;
-        public int End {
+        internal int End {
           get { return end_; }
           set {
             pb::Freezable.CheckMutable(this);
@@ -1328,26 +1301,30 @@
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class FieldDescriptorProto : pb::IMessage<FieldDescriptorProto> {
+  internal sealed partial class FieldDescriptorProto : pb::IMessage<FieldDescriptorProto> {
     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 pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_FieldDescriptorProto__Descriptor; }
+      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.Descriptor.MessageTypes[3]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<FieldDescriptorProto> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_FieldDescriptorProto__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public FieldDescriptorProto() { }
+    public FieldDescriptorProto() {
+      OnConstruction();
+    }
 
-    public FieldDescriptorProto(FieldDescriptorProto other) {
+    partial void OnConstruction();
+
+    public FieldDescriptorProto(FieldDescriptorProto other) : this() {
       name_ = other.name_;
       number_ = other.number_;
       label_ = other.label_;
@@ -1373,7 +1350,7 @@
 
     public const int NameFieldNumber = 1;
     private string name_ = "";
-    public string Name {
+    internal string Name {
       get { return name_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -1383,7 +1360,7 @@
 
     public const int NumberFieldNumber = 3;
     private int number_;
-    public int Number {
+    internal int Number {
       get { return number_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -1393,7 +1370,7 @@
 
     public const int LabelFieldNumber = 4;
     private global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Types.Label label_ = global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Types.Label.LABEL_OPTIONAL;
-    public global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Types.Label Label {
+    internal global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Types.Label Label {
       get { return label_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -1403,7 +1380,7 @@
 
     public const int TypeFieldNumber = 5;
     private global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Types.Type type_ = global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Types.Type.TYPE_DOUBLE;
-    public global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Types.Type Type {
+    internal global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Types.Type Type {
       get { return type_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -1413,7 +1390,7 @@
 
     public const int TypeNameFieldNumber = 6;
     private string typeName_ = "";
-    public string TypeName {
+    internal string TypeName {
       get { return typeName_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -1423,7 +1400,7 @@
 
     public const int ExtendeeFieldNumber = 2;
     private string extendee_ = "";
-    public string Extendee {
+    internal string Extendee {
       get { return extendee_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -1433,7 +1410,7 @@
 
     public const int DefaultValueFieldNumber = 7;
     private string defaultValue_ = "";
-    public string DefaultValue {
+    internal string DefaultValue {
       get { return defaultValue_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -1443,7 +1420,7 @@
 
     public const int OneofIndexFieldNumber = 9;
     private int oneofIndex_;
-    public int OneofIndex {
+    internal int OneofIndex {
       get { return oneofIndex_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -1453,7 +1430,7 @@
 
     public const int OptionsFieldNumber = 8;
     private global::Google.Protobuf.DescriptorProtos.FieldOptions options_;
-    public global::Google.Protobuf.DescriptorProtos.FieldOptions Options {
+    internal global::Google.Protobuf.DescriptorProtos.FieldOptions Options {
       get { return options_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -1662,7 +1639,7 @@
     #region Nested types
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
     public static partial class Types {
-      public enum Type {
+      internal enum Type {
         TYPE_DOUBLE = 1,
         TYPE_FLOAT = 2,
         TYPE_INT64 = 3,
@@ -1683,7 +1660,7 @@
         TYPE_SINT64 = 18,
       }
 
-      public enum Label {
+      internal enum Label {
         LABEL_OPTIONAL = 1,
         LABEL_REQUIRED = 2,
         LABEL_REPEATED = 3,
@@ -1695,26 +1672,30 @@
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class OneofDescriptorProto : pb::IMessage<OneofDescriptorProto> {
+  internal sealed partial class OneofDescriptorProto : pb::IMessage<OneofDescriptorProto> {
     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 pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_OneofDescriptorProto__Descriptor; }
+      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.Descriptor.MessageTypes[4]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<OneofDescriptorProto> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_OneofDescriptorProto__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public OneofDescriptorProto() { }
+    public OneofDescriptorProto() {
+      OnConstruction();
+    }
 
-    public OneofDescriptorProto(OneofDescriptorProto other) {
+    partial void OnConstruction();
+
+    public OneofDescriptorProto(OneofDescriptorProto other) : this() {
       name_ = other.name_;
     }
 
@@ -1731,7 +1712,7 @@
 
     public const int NameFieldNumber = 1;
     private string name_ = "";
-    public string Name {
+    internal string Name {
       get { return name_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -1806,26 +1787,30 @@
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class EnumDescriptorProto : pb::IMessage<EnumDescriptorProto> {
+  internal sealed partial class EnumDescriptorProto : pb::IMessage<EnumDescriptorProto> {
     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 pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_EnumDescriptorProto__Descriptor; }
+      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.Descriptor.MessageTypes[5]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<EnumDescriptorProto> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_EnumDescriptorProto__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public EnumDescriptorProto() { }
+    public EnumDescriptorProto() {
+      OnConstruction();
+    }
 
-    public EnumDescriptorProto(EnumDescriptorProto other) {
+    partial void OnConstruction();
+
+    public EnumDescriptorProto(EnumDescriptorProto other) : this() {
       name_ = other.name_;
       value_ = other.value_.Clone();
       Options = other.options_ != null ? other.Options.Clone() : null;
@@ -1846,7 +1831,7 @@
 
     public const int NameFieldNumber = 1;
     private string name_ = "";
-    public string Name {
+    internal string Name {
       get { return name_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -1858,13 +1843,13 @@
     private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.EnumValueDescriptorProto> _repeated_value_codec
         = pb::FieldCodec.ForMessage(18, global::Google.Protobuf.DescriptorProtos.EnumValueDescriptorProto.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.EnumValueDescriptorProto> value_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.EnumValueDescriptorProto>();
-    public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.EnumValueDescriptorProto> Value {
+    internal pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.EnumValueDescriptorProto> Value {
       get { return value_; }
     }
 
     public const int OptionsFieldNumber = 3;
     private global::Google.Protobuf.DescriptorProtos.EnumOptions options_;
-    public global::Google.Protobuf.DescriptorProtos.EnumOptions Options {
+    internal global::Google.Protobuf.DescriptorProtos.EnumOptions Options {
       get { return options_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -1970,26 +1955,30 @@
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class EnumValueDescriptorProto : pb::IMessage<EnumValueDescriptorProto> {
+  internal sealed partial class EnumValueDescriptorProto : pb::IMessage<EnumValueDescriptorProto> {
     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 pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_EnumValueDescriptorProto__Descriptor; }
+      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.Descriptor.MessageTypes[6]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<EnumValueDescriptorProto> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_EnumValueDescriptorProto__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public EnumValueDescriptorProto() { }
+    public EnumValueDescriptorProto() {
+      OnConstruction();
+    }
 
-    public EnumValueDescriptorProto(EnumValueDescriptorProto other) {
+    partial void OnConstruction();
+
+    public EnumValueDescriptorProto(EnumValueDescriptorProto other) : this() {
       name_ = other.name_;
       number_ = other.number_;
       Options = other.options_ != null ? other.Options.Clone() : null;
@@ -2009,7 +1998,7 @@
 
     public const int NameFieldNumber = 1;
     private string name_ = "";
-    public string Name {
+    internal string Name {
       get { return name_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -2019,7 +2008,7 @@
 
     public const int NumberFieldNumber = 2;
     private int number_;
-    public int Number {
+    internal int Number {
       get { return number_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -2029,7 +2018,7 @@
 
     public const int OptionsFieldNumber = 3;
     private global::Google.Protobuf.DescriptorProtos.EnumValueOptions options_;
-    public global::Google.Protobuf.DescriptorProtos.EnumValueOptions Options {
+    internal global::Google.Protobuf.DescriptorProtos.EnumValueOptions Options {
       get { return options_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -2142,26 +2131,30 @@
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class ServiceDescriptorProto : pb::IMessage<ServiceDescriptorProto> {
+  internal sealed partial class ServiceDescriptorProto : pb::IMessage<ServiceDescriptorProto> {
     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 pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_ServiceDescriptorProto__Descriptor; }
+      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.Descriptor.MessageTypes[7]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<ServiceDescriptorProto> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_ServiceDescriptorProto__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public ServiceDescriptorProto() { }
+    public ServiceDescriptorProto() {
+      OnConstruction();
+    }
 
-    public ServiceDescriptorProto(ServiceDescriptorProto other) {
+    partial void OnConstruction();
+
+    public ServiceDescriptorProto(ServiceDescriptorProto other) : this() {
       name_ = other.name_;
       method_ = other.method_.Clone();
       Options = other.options_ != null ? other.Options.Clone() : null;
@@ -2182,7 +2175,7 @@
 
     public const int NameFieldNumber = 1;
     private string name_ = "";
-    public string Name {
+    internal string Name {
       get { return name_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -2194,13 +2187,13 @@
     private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.MethodDescriptorProto> _repeated_method_codec
         = pb::FieldCodec.ForMessage(18, global::Google.Protobuf.DescriptorProtos.MethodDescriptorProto.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.MethodDescriptorProto> method_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.MethodDescriptorProto>();
-    public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.MethodDescriptorProto> Method {
+    internal pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.MethodDescriptorProto> Method {
       get { return method_; }
     }
 
     public const int OptionsFieldNumber = 3;
     private global::Google.Protobuf.DescriptorProtos.ServiceOptions options_;
-    public global::Google.Protobuf.DescriptorProtos.ServiceOptions Options {
+    internal global::Google.Protobuf.DescriptorProtos.ServiceOptions Options {
       get { return options_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -2306,26 +2299,30 @@
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class MethodDescriptorProto : pb::IMessage<MethodDescriptorProto> {
+  internal sealed partial class MethodDescriptorProto : pb::IMessage<MethodDescriptorProto> {
     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 pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_MethodDescriptorProto__Descriptor; }
+      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.Descriptor.MessageTypes[8]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<MethodDescriptorProto> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_MethodDescriptorProto__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public MethodDescriptorProto() { }
+    public MethodDescriptorProto() {
+      OnConstruction();
+    }
 
-    public MethodDescriptorProto(MethodDescriptorProto other) {
+    partial void OnConstruction();
+
+    public MethodDescriptorProto(MethodDescriptorProto other) : this() {
       name_ = other.name_;
       inputType_ = other.inputType_;
       outputType_ = other.outputType_;
@@ -2348,7 +2345,7 @@
 
     public const int NameFieldNumber = 1;
     private string name_ = "";
-    public string Name {
+    internal string Name {
       get { return name_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -2358,7 +2355,7 @@
 
     public const int InputTypeFieldNumber = 2;
     private string inputType_ = "";
-    public string InputType {
+    internal string InputType {
       get { return inputType_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -2368,7 +2365,7 @@
 
     public const int OutputTypeFieldNumber = 3;
     private string outputType_ = "";
-    public string OutputType {
+    internal string OutputType {
       get { return outputType_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -2378,7 +2375,7 @@
 
     public const int OptionsFieldNumber = 4;
     private global::Google.Protobuf.DescriptorProtos.MethodOptions options_;
-    public global::Google.Protobuf.DescriptorProtos.MethodOptions Options {
+    internal global::Google.Protobuf.DescriptorProtos.MethodOptions Options {
       get { return options_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -2388,7 +2385,7 @@
 
     public const int ClientStreamingFieldNumber = 5;
     private bool clientStreaming_;
-    public bool ClientStreaming {
+    internal bool ClientStreaming {
       get { return clientStreaming_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -2398,7 +2395,7 @@
 
     public const int ServerStreamingFieldNumber = 6;
     private bool serverStreaming_;
-    public bool ServerStreaming {
+    internal bool ServerStreaming {
       get { return serverStreaming_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -2559,26 +2556,30 @@
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class FileOptions : pb::IMessage<FileOptions> {
+  internal sealed partial class FileOptions : pb::IMessage<FileOptions> {
     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 pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_FileOptions__Descriptor; }
+      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.Descriptor.MessageTypes[9]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<FileOptions> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_FileOptions__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public FileOptions() { }
+    public FileOptions() {
+      OnConstruction();
+    }
 
-    public FileOptions(FileOptions other) {
+    partial void OnConstruction();
+
+    public FileOptions(FileOptions other) : this() {
       javaPackage_ = other.javaPackage_;
       javaOuterClassname_ = other.javaOuterClassname_;
       javaMultipleFiles_ = other.javaMultipleFiles_;
@@ -2610,7 +2611,7 @@
 
     public const int JavaPackageFieldNumber = 1;
     private string javaPackage_ = "";
-    public string JavaPackage {
+    internal string JavaPackage {
       get { return javaPackage_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -2620,7 +2621,7 @@
 
     public const int JavaOuterClassnameFieldNumber = 8;
     private string javaOuterClassname_ = "";
-    public string JavaOuterClassname {
+    internal string JavaOuterClassname {
       get { return javaOuterClassname_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -2630,7 +2631,7 @@
 
     public const int JavaMultipleFilesFieldNumber = 10;
     private bool javaMultipleFiles_;
-    public bool JavaMultipleFiles {
+    internal bool JavaMultipleFiles {
       get { return javaMultipleFiles_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -2640,7 +2641,7 @@
 
     public const int JavaGenerateEqualsAndHashFieldNumber = 20;
     private bool javaGenerateEqualsAndHash_;
-    public bool JavaGenerateEqualsAndHash {
+    internal bool JavaGenerateEqualsAndHash {
       get { return javaGenerateEqualsAndHash_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -2650,7 +2651,7 @@
 
     public const int JavaStringCheckUtf8FieldNumber = 27;
     private bool javaStringCheckUtf8_;
-    public bool JavaStringCheckUtf8 {
+    internal bool JavaStringCheckUtf8 {
       get { return javaStringCheckUtf8_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -2660,7 +2661,7 @@
 
     public const int OptimizeForFieldNumber = 9;
     private global::Google.Protobuf.DescriptorProtos.FileOptions.Types.OptimizeMode optimizeFor_ = global::Google.Protobuf.DescriptorProtos.FileOptions.Types.OptimizeMode.SPEED;
-    public global::Google.Protobuf.DescriptorProtos.FileOptions.Types.OptimizeMode OptimizeFor {
+    internal global::Google.Protobuf.DescriptorProtos.FileOptions.Types.OptimizeMode OptimizeFor {
       get { return optimizeFor_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -2670,7 +2671,7 @@
 
     public const int GoPackageFieldNumber = 11;
     private string goPackage_ = "";
-    public string GoPackage {
+    internal string GoPackage {
       get { return goPackage_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -2680,7 +2681,7 @@
 
     public const int CcGenericServicesFieldNumber = 16;
     private bool ccGenericServices_;
-    public bool CcGenericServices {
+    internal bool CcGenericServices {
       get { return ccGenericServices_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -2690,7 +2691,7 @@
 
     public const int JavaGenericServicesFieldNumber = 17;
     private bool javaGenericServices_;
-    public bool JavaGenericServices {
+    internal bool JavaGenericServices {
       get { return javaGenericServices_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -2700,7 +2701,7 @@
 
     public const int PyGenericServicesFieldNumber = 18;
     private bool pyGenericServices_;
-    public bool PyGenericServices {
+    internal bool PyGenericServices {
       get { return pyGenericServices_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -2710,7 +2711,7 @@
 
     public const int DeprecatedFieldNumber = 23;
     private bool deprecated_;
-    public bool Deprecated {
+    internal bool Deprecated {
       get { return deprecated_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -2720,7 +2721,7 @@
 
     public const int CcEnableArenasFieldNumber = 31;
     private bool ccEnableArenas_;
-    public bool CcEnableArenas {
+    internal bool CcEnableArenas {
       get { return ccEnableArenas_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -2730,7 +2731,7 @@
 
     public const int ObjcClassPrefixFieldNumber = 36;
     private string objcClassPrefix_ = "";
-    public string ObjcClassPrefix {
+    internal string ObjcClassPrefix {
       get { return objcClassPrefix_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -2740,7 +2741,7 @@
 
     public const int CsharpNamespaceFieldNumber = 37;
     private string csharpNamespace_ = "";
-    public string CsharpNamespace {
+    internal string CsharpNamespace {
       get { return csharpNamespace_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -2752,7 +2753,7 @@
     private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> _repeated_uninterpretedOption_codec
         = pb::FieldCodec.ForMessage(7994, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> uninterpretedOption_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption>();
-    public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> UninterpretedOption {
+    internal pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> UninterpretedOption {
       get { return uninterpretedOption_; }
     }
 
@@ -3040,7 +3041,7 @@
     #region Nested types
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
     public static partial class Types {
-      public enum OptimizeMode {
+      internal enum OptimizeMode {
         SPEED = 1,
         CODE_SIZE = 2,
         LITE_RUNTIME = 3,
@@ -3052,26 +3053,30 @@
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class MessageOptions : pb::IMessage<MessageOptions> {
+  internal sealed partial class MessageOptions : pb::IMessage<MessageOptions> {
     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 pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_MessageOptions__Descriptor; }
+      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.Descriptor.MessageTypes[10]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<MessageOptions> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_MessageOptions__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public MessageOptions() { }
+    public MessageOptions() {
+      OnConstruction();
+    }
 
-    public MessageOptions(MessageOptions other) {
+    partial void OnConstruction();
+
+    public MessageOptions(MessageOptions other) : this() {
       messageSetWireFormat_ = other.messageSetWireFormat_;
       noStandardDescriptorAccessor_ = other.noStandardDescriptorAccessor_;
       deprecated_ = other.deprecated_;
@@ -3093,7 +3098,7 @@
 
     public const int MessageSetWireFormatFieldNumber = 1;
     private bool messageSetWireFormat_;
-    public bool MessageSetWireFormat {
+    internal bool MessageSetWireFormat {
       get { return messageSetWireFormat_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -3103,7 +3108,7 @@
 
     public const int NoStandardDescriptorAccessorFieldNumber = 2;
     private bool noStandardDescriptorAccessor_;
-    public bool NoStandardDescriptorAccessor {
+    internal bool NoStandardDescriptorAccessor {
       get { return noStandardDescriptorAccessor_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -3113,7 +3118,7 @@
 
     public const int DeprecatedFieldNumber = 3;
     private bool deprecated_;
-    public bool Deprecated {
+    internal bool Deprecated {
       get { return deprecated_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -3123,7 +3128,7 @@
 
     public const int MapEntryFieldNumber = 7;
     private bool mapEntry_;
-    public bool MapEntry {
+    internal bool MapEntry {
       get { return mapEntry_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -3135,7 +3140,7 @@
     private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> _repeated_uninterpretedOption_codec
         = pb::FieldCodec.ForMessage(7994, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> uninterpretedOption_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption>();
-    public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> UninterpretedOption {
+    internal pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> UninterpretedOption {
       get { return uninterpretedOption_; }
     }
 
@@ -3263,26 +3268,30 @@
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class FieldOptions : pb::IMessage<FieldOptions> {
+  internal sealed partial class FieldOptions : pb::IMessage<FieldOptions> {
     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 pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_FieldOptions__Descriptor; }
+      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.Descriptor.MessageTypes[11]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<FieldOptions> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_FieldOptions__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public FieldOptions() { }
+    public FieldOptions() {
+      OnConstruction();
+    }
 
-    public FieldOptions(FieldOptions other) {
+    partial void OnConstruction();
+
+    public FieldOptions(FieldOptions other) : this() {
       ctype_ = other.ctype_;
       packed_ = other.packed_;
       jstype_ = other.jstype_;
@@ -3306,7 +3315,7 @@
 
     public const int CtypeFieldNumber = 1;
     private global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.CType ctype_ = global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.CType.STRING;
-    public global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.CType Ctype {
+    internal global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.CType Ctype {
       get { return ctype_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -3316,7 +3325,7 @@
 
     public const int PackedFieldNumber = 2;
     private bool packed_;
-    public bool Packed {
+    internal bool Packed {
       get { return packed_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -3326,7 +3335,7 @@
 
     public const int JstypeFieldNumber = 6;
     private global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.JSType jstype_ = global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.JSType.JS_NORMAL;
-    public global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.JSType Jstype {
+    internal global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.JSType Jstype {
       get { return jstype_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -3336,7 +3345,7 @@
 
     public const int LazyFieldNumber = 5;
     private bool lazy_;
-    public bool Lazy {
+    internal bool Lazy {
       get { return lazy_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -3346,7 +3355,7 @@
 
     public const int DeprecatedFieldNumber = 3;
     private bool deprecated_;
-    public bool Deprecated {
+    internal bool Deprecated {
       get { return deprecated_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -3356,7 +3365,7 @@
 
     public const int WeakFieldNumber = 10;
     private bool weak_;
-    public bool Weak {
+    internal bool Weak {
       get { return weak_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -3368,7 +3377,7 @@
     private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> _repeated_uninterpretedOption_codec
         = pb::FieldCodec.ForMessage(7994, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> uninterpretedOption_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption>();
-    public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> UninterpretedOption {
+    internal pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> UninterpretedOption {
       get { return uninterpretedOption_; }
     }
 
@@ -3528,13 +3537,13 @@
     #region Nested types
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
     public static partial class Types {
-      public enum CType {
+      internal enum CType {
         STRING = 0,
         CORD = 1,
         STRING_PIECE = 2,
       }
 
-      public enum JSType {
+      internal enum JSType {
         JS_NORMAL = 0,
         JS_STRING = 1,
         JS_NUMBER = 2,
@@ -3546,26 +3555,30 @@
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class EnumOptions : pb::IMessage<EnumOptions> {
+  internal sealed partial class EnumOptions : pb::IMessage<EnumOptions> {
     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 pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_EnumOptions__Descriptor; }
+      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.Descriptor.MessageTypes[12]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<EnumOptions> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_EnumOptions__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public EnumOptions() { }
+    public EnumOptions() {
+      OnConstruction();
+    }
 
-    public EnumOptions(EnumOptions other) {
+    partial void OnConstruction();
+
+    public EnumOptions(EnumOptions other) : this() {
       allowAlias_ = other.allowAlias_;
       deprecated_ = other.deprecated_;
       uninterpretedOption_ = other.uninterpretedOption_.Clone();
@@ -3585,7 +3598,7 @@
 
     public const int AllowAliasFieldNumber = 2;
     private bool allowAlias_;
-    public bool AllowAlias {
+    internal bool AllowAlias {
       get { return allowAlias_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -3595,7 +3608,7 @@
 
     public const int DeprecatedFieldNumber = 3;
     private bool deprecated_;
-    public bool Deprecated {
+    internal bool Deprecated {
       get { return deprecated_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -3607,7 +3620,7 @@
     private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> _repeated_uninterpretedOption_codec
         = pb::FieldCodec.ForMessage(7994, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> uninterpretedOption_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption>();
-    public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> UninterpretedOption {
+    internal pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> UninterpretedOption {
       get { return uninterpretedOption_; }
     }
 
@@ -3703,26 +3716,30 @@
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class EnumValueOptions : pb::IMessage<EnumValueOptions> {
+  internal sealed partial class EnumValueOptions : pb::IMessage<EnumValueOptions> {
     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 pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_EnumValueOptions__Descriptor; }
+      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.Descriptor.MessageTypes[13]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<EnumValueOptions> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_EnumValueOptions__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public EnumValueOptions() { }
+    public EnumValueOptions() {
+      OnConstruction();
+    }
 
-    public EnumValueOptions(EnumValueOptions other) {
+    partial void OnConstruction();
+
+    public EnumValueOptions(EnumValueOptions other) : this() {
       deprecated_ = other.deprecated_;
       uninterpretedOption_ = other.uninterpretedOption_.Clone();
     }
@@ -3741,7 +3758,7 @@
 
     public const int DeprecatedFieldNumber = 1;
     private bool deprecated_;
-    public bool Deprecated {
+    internal bool Deprecated {
       get { return deprecated_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -3753,7 +3770,7 @@
     private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> _repeated_uninterpretedOption_codec
         = pb::FieldCodec.ForMessage(7994, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> uninterpretedOption_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption>();
-    public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> UninterpretedOption {
+    internal pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> UninterpretedOption {
       get { return uninterpretedOption_; }
     }
 
@@ -3833,26 +3850,30 @@
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class ServiceOptions : pb::IMessage<ServiceOptions> {
+  internal sealed partial class ServiceOptions : pb::IMessage<ServiceOptions> {
     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 pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_ServiceOptions__Descriptor; }
+      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.Descriptor.MessageTypes[14]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<ServiceOptions> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_ServiceOptions__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public ServiceOptions() { }
+    public ServiceOptions() {
+      OnConstruction();
+    }
 
-    public ServiceOptions(ServiceOptions other) {
+    partial void OnConstruction();
+
+    public ServiceOptions(ServiceOptions other) : this() {
       deprecated_ = other.deprecated_;
       uninterpretedOption_ = other.uninterpretedOption_.Clone();
     }
@@ -3871,7 +3892,7 @@
 
     public const int DeprecatedFieldNumber = 33;
     private bool deprecated_;
-    public bool Deprecated {
+    internal bool Deprecated {
       get { return deprecated_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -3883,7 +3904,7 @@
     private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> _repeated_uninterpretedOption_codec
         = pb::FieldCodec.ForMessage(7994, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> uninterpretedOption_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption>();
-    public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> UninterpretedOption {
+    internal pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> UninterpretedOption {
       get { return uninterpretedOption_; }
     }
 
@@ -3963,26 +3984,30 @@
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class MethodOptions : pb::IMessage<MethodOptions> {
+  internal sealed partial class MethodOptions : pb::IMessage<MethodOptions> {
     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 pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_MethodOptions__Descriptor; }
+      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.Descriptor.MessageTypes[15]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<MethodOptions> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_MethodOptions__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public MethodOptions() { }
+    public MethodOptions() {
+      OnConstruction();
+    }
 
-    public MethodOptions(MethodOptions other) {
+    partial void OnConstruction();
+
+    public MethodOptions(MethodOptions other) : this() {
       deprecated_ = other.deprecated_;
       uninterpretedOption_ = other.uninterpretedOption_.Clone();
     }
@@ -4001,7 +4026,7 @@
 
     public const int DeprecatedFieldNumber = 33;
     private bool deprecated_;
-    public bool Deprecated {
+    internal bool Deprecated {
       get { return deprecated_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -4013,7 +4038,7 @@
     private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> _repeated_uninterpretedOption_codec
         = pb::FieldCodec.ForMessage(7994, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> uninterpretedOption_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption>();
-    public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> UninterpretedOption {
+    internal pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> UninterpretedOption {
       get { return uninterpretedOption_; }
     }
 
@@ -4093,26 +4118,30 @@
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class UninterpretedOption : pb::IMessage<UninterpretedOption> {
+  internal sealed partial class UninterpretedOption : pb::IMessage<UninterpretedOption> {
     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 pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_UninterpretedOption__Descriptor; }
+      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.Descriptor.MessageTypes[16]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<UninterpretedOption> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_UninterpretedOption__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public UninterpretedOption() { }
+    public UninterpretedOption() {
+      OnConstruction();
+    }
 
-    public UninterpretedOption(UninterpretedOption other) {
+    partial void OnConstruction();
+
+    public UninterpretedOption(UninterpretedOption other) : this() {
       name_ = other.name_.Clone();
       identifierValue_ = other.identifierValue_;
       positiveIntValue_ = other.positiveIntValue_;
@@ -4138,13 +4167,13 @@
     private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Types.NamePart> _repeated_name_codec
         = pb::FieldCodec.ForMessage(18, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Types.NamePart.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Types.NamePart> name_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Types.NamePart>();
-    public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Types.NamePart> Name {
+    internal pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Types.NamePart> Name {
       get { return name_; }
     }
 
     public const int IdentifierValueFieldNumber = 3;
     private string identifierValue_ = "";
-    public string IdentifierValue {
+    internal string IdentifierValue {
       get { return identifierValue_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -4154,7 +4183,7 @@
 
     public const int PositiveIntValueFieldNumber = 4;
     private ulong positiveIntValue_;
-    public ulong PositiveIntValue {
+    internal ulong PositiveIntValue {
       get { return positiveIntValue_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -4164,7 +4193,7 @@
 
     public const int NegativeIntValueFieldNumber = 5;
     private long negativeIntValue_;
-    public long NegativeIntValue {
+    internal long NegativeIntValue {
       get { return negativeIntValue_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -4174,7 +4203,7 @@
 
     public const int DoubleValueFieldNumber = 6;
     private double doubleValue_;
-    public double DoubleValue {
+    internal double DoubleValue {
       get { return doubleValue_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -4184,7 +4213,7 @@
 
     public const int StringValueFieldNumber = 7;
     private pb::ByteString stringValue_ = pb::ByteString.Empty;
-    public pb::ByteString StringValue {
+    internal pb::ByteString StringValue {
       get { return stringValue_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -4194,7 +4223,7 @@
 
     public const int AggregateValueFieldNumber = 8;
     private string aggregateValue_ = "";
-    public string AggregateValue {
+    internal string AggregateValue {
       get { return aggregateValue_; }
       set {
         pb::Freezable.CheckMutable(this);
@@ -4359,26 +4388,30 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
     public static partial class Types {
       [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-      public sealed partial class NamePart : pb::IMessage<NamePart> {
+      internal sealed partial class NamePart : pb::IMessage<NamePart> {
         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 pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_UninterpretedOption_NamePart__Descriptor; }
+          get { return global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Descriptor.NestedTypes[0]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<NamePart> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_UninterpretedOption_NamePart__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public NamePart() { }
+        public NamePart() {
+          OnConstruction();
+        }
 
-        public NamePart(NamePart other) {
+        partial void OnConstruction();
+
+        public NamePart(NamePart other) : this() {
           namePart_ = other.namePart_;
           isExtension_ = other.isExtension_;
         }
@@ -4396,7 +4429,7 @@
 
         public const int NamePart_FieldNumber = 1;
         private string namePart_ = "";
-        public string NamePart_ {
+        internal string NamePart_ {
           get { return namePart_; }
           set {
             pb::Freezable.CheckMutable(this);
@@ -4406,7 +4439,7 @@
 
         public const int IsExtensionFieldNumber = 2;
         private bool isExtension_;
-        public bool IsExtension {
+        internal bool IsExtension {
           get { return isExtension_; }
           set {
             pb::Freezable.CheckMutable(this);
@@ -4502,26 +4535,30 @@
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class SourceCodeInfo : pb::IMessage<SourceCodeInfo> {
+  internal sealed partial class SourceCodeInfo : pb::IMessage<SourceCodeInfo> {
     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 pbd::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_SourceCodeInfo__Descriptor; }
+      get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.Descriptor.MessageTypes[17]; }
     }
 
-    public pb::FieldAccess.FieldAccessorTable<SourceCodeInfo> Fields {
+    public pb::FieldAccess.FieldAccessorTable Fields {
       get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_SourceCodeInfo__FieldAccessorTable; }
     }
 
     private bool _frozen = false;
     public bool IsFrozen { get { return _frozen; } }
 
-    public SourceCodeInfo() { }
+    public SourceCodeInfo() {
+      OnConstruction();
+    }
 
-    public SourceCodeInfo(SourceCodeInfo other) {
+    partial void OnConstruction();
+
+    public SourceCodeInfo(SourceCodeInfo other) : this() {
       location_ = other.location_.Clone();
     }
 
@@ -4541,7 +4578,7 @@
     private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.SourceCodeInfo.Types.Location> _repeated_location_codec
         = pb::FieldCodec.ForMessage(10, global::Google.Protobuf.DescriptorProtos.SourceCodeInfo.Types.Location.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.SourceCodeInfo.Types.Location> location_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.SourceCodeInfo.Types.Location>();
-    public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.SourceCodeInfo.Types.Location> Location {
+    internal pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.SourceCodeInfo.Types.Location> Location {
       get { return location_; }
     }
 
@@ -4606,26 +4643,30 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
     public static partial class Types {
       [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-      public sealed partial class Location : pb::IMessage<Location> {
+      internal sealed partial class Location : pb::IMessage<Location> {
         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 pbd::MessageDescriptor Descriptor {
-          get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_SourceCodeInfo_Location__Descriptor; }
+          get { return global::Google.Protobuf.DescriptorProtos.SourceCodeInfo.Descriptor.NestedTypes[0]; }
         }
 
-        public pb::FieldAccess.FieldAccessorTable<Location> Fields {
+        public pb::FieldAccess.FieldAccessorTable Fields {
           get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_SourceCodeInfo_Location__FieldAccessorTable; }
         }
 
         private bool _frozen = false;
         public bool IsFrozen { get { return _frozen; } }
 
-        public Location() { }
+        public Location() {
+          OnConstruction();
+        }
 
-        public Location(Location other) {
+        partial void OnConstruction();
+
+        public Location(Location other) : this() {
           path_ = other.path_.Clone();
           span_ = other.span_.Clone();
           leadingComments_ = other.leadingComments_;
@@ -4651,7 +4692,7 @@
         private static readonly pb::FieldCodec<int> _repeated_path_codec
             = pb::FieldCodec.ForInt32(10);
         private readonly pbc::RepeatedField<int> path_ = new pbc::RepeatedField<int>();
-        public pbc::RepeatedField<int> Path {
+        internal pbc::RepeatedField<int> Path {
           get { return path_; }
         }
 
@@ -4659,13 +4700,13 @@
         private static readonly pb::FieldCodec<int> _repeated_span_codec
             = pb::FieldCodec.ForInt32(18);
         private readonly pbc::RepeatedField<int> span_ = new pbc::RepeatedField<int>();
-        public pbc::RepeatedField<int> Span {
+        internal pbc::RepeatedField<int> Span {
           get { return span_; }
         }
 
         public const int LeadingCommentsFieldNumber = 3;
         private string leadingComments_ = "";
-        public string LeadingComments {
+        internal string LeadingComments {
           get { return leadingComments_; }
           set {
             pb::Freezable.CheckMutable(this);
@@ -4675,7 +4716,7 @@
 
         public const int TrailingCommentsFieldNumber = 4;
         private string trailingComments_ = "";
-        public string TrailingComments {
+        internal string TrailingComments {
           get { return trailingComments_; }
           set {
             pb::Freezable.CheckMutable(this);
@@ -4687,7 +4728,7 @@
         private static readonly pb::FieldCodec<string> _repeated_leadingDetachedComments_codec
             = pb::FieldCodec.ForString(50);
         private readonly pbc::RepeatedField<string> leadingDetachedComments_ = new pbc::RepeatedField<string>();
-        public pbc::RepeatedField<string> LeadingDetachedComments {
+        internal pbc::RepeatedField<string> LeadingDetachedComments {
           get { return leadingDetachedComments_; }
         }
 
diff --git a/csharp/src/ProtocolBuffers/DescriptorProtos/PartialClasses.cs b/csharp/src/ProtocolBuffers/DescriptorProtos/PartialClasses.cs
index 15f339b..dc19cda 100644
--- a/csharp/src/ProtocolBuffers/DescriptorProtos/PartialClasses.cs
+++ b/csharp/src/ProtocolBuffers/DescriptorProtos/PartialClasses.cs
@@ -30,36 +30,18 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

 #endregion

 

-// This file just contains partial classes for each of the

-// autogenerated classes, so that they implement

-// IDescriptorProto

+// This file just contains partial classes for any autogenerated classes that need additional support.

 namespace Google.Protobuf.DescriptorProtos

 {

-    public partial class DescriptorProto : IDescriptorProto<MessageOptions>

+    internal partial class FieldDescriptorProto

     {

-    }

-

-    public partial class EnumDescriptorProto : IDescriptorProto<EnumOptions>

-    {

-    }

-

-    public partial class EnumValueDescriptorProto : IDescriptorProto<EnumValueOptions>

-    {

-    }

-

-    public partial class FieldDescriptorProto : IDescriptorProto<FieldOptions>

-    {

-    }

-

-    public partial class FileDescriptorProto : IDescriptorProto<FileOptions>

-    {

-    }

-

-    public partial class MethodDescriptorProto : IDescriptorProto<MethodOptions>

-    {

-    }

-

-    public partial class ServiceDescriptorProto : IDescriptorProto<ServiceOptions>

-    {

+        // We can't tell the difference between "explicitly set to 0" and "not set"

+        // in proto3, but we need to tell the difference for OneofIndex. descriptor.proto

+        // is really a proto2 file, but the runtime doesn't know about proto2 semantics...

+        // We fake it by defaulting to -1.

+        partial void OnConstruction()

+        {

+            OneofIndex = -1;

+        }

     }

 }
\ No newline at end of file
diff --git a/csharp/src/ProtocolBuffers/Descriptors/DescriptorBase.cs b/csharp/src/ProtocolBuffers/Descriptors/DescriptorBase.cs
index ccde34a..0eb7121 100644
--- a/csharp/src/ProtocolBuffers/Descriptors/DescriptorBase.cs
+++ b/csharp/src/ProtocolBuffers/Descriptors/DescriptorBase.cs
@@ -34,61 +34,36 @@
 

 namespace Google.Protobuf.Descriptors

 {

-    // TODO(jonskeet): The descriptor type hierarchy needs changing so that we can hide the descriptor protos.

     /// <summary>

     /// Base class for nearly all descriptors, providing common functionality.

     /// </summary>

-    /// <typeparam name="TProto">Type of the protocol buffer form of this descriptor</typeparam>

-    /// <typeparam name="TOptions">Type of the options protocol buffer for this descriptor</typeparam>

-    public abstract class DescriptorBase<TProto, TOptions> : IDescriptor<TProto>

-        where TProto : IMessage, IDescriptorProto<TOptions>

+    public abstract class DescriptorBase : IDescriptor

     {

-        private TProto proto;

         private readonly FileDescriptor file;

         private readonly string fullName;

+        private readonly int index;

 

-        protected DescriptorBase(TProto proto, FileDescriptor file, string fullName)

+        internal DescriptorBase(FileDescriptor file, string fullName, int index)

         {

-            this.proto = proto;

             this.file = file;

             this.fullName = fullName;

+            this.index = index;

         }

 

-        internal virtual void ReplaceProto(TProto newProto)

+        /// <value>

+        /// The index of this descriptor within its parent descriptor. 

+        /// </value>

+        /// <remarks>

+        /// This returns the index of this descriptor within its parent, for

+        /// this descriptor's type. (There can be duplicate values for different

+        /// types, e.g. one enum type with index 0 and one message type with index 0.)

+        /// </remarks>

+        public int Index

         {

-            this.proto = newProto;

+            get { return index; }

         }

 

-        protected static string ComputeFullName(FileDescriptor file, MessageDescriptor parent, string name)

-        {

-            if (parent != null)

-            {

-                return parent.FullName + "." + name;

-            }

-            if (file.Package.Length > 0)

-            {

-                return file.Package + "." + name;

-            }

-            return name;

-        }

-

-        IMessage IDescriptor.Proto

-        {

-            get { return proto; }

-        }

-

-        /// <summary>

-        /// Returns the protocol buffer form of this descriptor.

-        /// </summary>

-        public TProto Proto

-        {

-            get { return proto; }

-        }

-

-        public TOptions Options

-        {

-            get { return proto.Options; }

-        }

+        public abstract string Name { get; }

 

         /// <summary>

         /// The fully qualified name of the descriptor's target.

@@ -98,14 +73,6 @@
             get { return fullName; }

         }

 

-        /// <summary>

-        /// The brief name of the descriptor's target.

-        /// </summary>

-        public string Name

-        {

-            get { return proto.Name; }

-        }

-

         /// <value>

         /// The file this descriptor was declared in.

         /// </value>

diff --git a/csharp/src/ProtocolBuffers/Descriptors/DescriptorPool.cs b/csharp/src/ProtocolBuffers/Descriptors/DescriptorPool.cs
index 57c4ba0..b07af06 100644
--- a/csharp/src/ProtocolBuffers/Descriptors/DescriptorPool.cs
+++ b/csharp/src/ProtocolBuffers/Descriptors/DescriptorPool.cs
@@ -257,7 +257,7 @@
         /// or unqualified. C++-like name lookup semantics are used to search for the

         /// matching descriptor.

         /// </summary>

-        public IDescriptor LookupSymbol(string name, IDescriptor relativeTo)

+        internal IDescriptor LookupSymbol(string name, IDescriptor relativeTo)

         {

             // TODO(jonskeet):  This could be optimized in a number of ways.

 

diff --git a/csharp/src/ProtocolBuffers/Descriptors/EnumDescriptor.cs b/csharp/src/ProtocolBuffers/Descriptors/EnumDescriptor.cs
index 9f10990..a6db526 100644
--- a/csharp/src/ProtocolBuffers/Descriptors/EnumDescriptor.cs
+++ b/csharp/src/ProtocolBuffers/Descriptors/EnumDescriptor.cs
@@ -38,14 +38,16 @@
     /// <summary>

     /// Descriptor for an enum type in a .proto file.

     /// </summary>

-    public sealed class EnumDescriptor : IndexedDescriptorBase<EnumDescriptorProto, EnumOptions>

+    public sealed class EnumDescriptor : DescriptorBase

     {

+        private readonly EnumDescriptorProto proto;

         private readonly MessageDescriptor containingType;

         private readonly IList<EnumValueDescriptor> values;

 

         internal EnumDescriptor(EnumDescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int index)

-            : base(proto, file, ComputeFullName(file, parent, proto.Name), index)

+            : base(file, file.ComputeFullName(parent, proto.Name), index)

         {

+            this.proto = proto;

             containingType = parent;

 

             if (proto.Value.Count == 0)

@@ -61,6 +63,13 @@
             File.DescriptorPool.AddSymbol(this);

         }

 

+        internal EnumDescriptorProto Proto { get { return proto; } }

+

+        /// <summary>

+        /// The brief name of the descriptor's target.

+        /// </summary>

+        public override string Name { get { return proto.Name; } }

+

         /// <value>

         /// If this is a nested type, get the outer descriptor, otherwise null.

         /// </value>

@@ -95,14 +104,5 @@
         {

             return File.DescriptorPool.FindSymbol<EnumValueDescriptor>(FullName + "." + name);

         }

-

-        internal override void ReplaceProto(EnumDescriptorProto newProto)

-        {

-            base.ReplaceProto(newProto);

-            for (int i = 0; i < values.Count; i++)

-            {

-                values[i].ReplaceProto(newProto.Value[i]);

-            }

-        }

     }

 }
\ No newline at end of file
diff --git a/csharp/src/ProtocolBuffers/Descriptors/EnumValueDescriptor.cs b/csharp/src/ProtocolBuffers/Descriptors/EnumValueDescriptor.cs
index b553ee5..e609b1f 100644
--- a/csharp/src/ProtocolBuffers/Descriptors/EnumValueDescriptor.cs
+++ b/csharp/src/ProtocolBuffers/Descriptors/EnumValueDescriptor.cs
@@ -37,27 +37,27 @@
     /// <summary>

     /// Descriptor for a single enum value within an enum in a .proto file.

     /// </summary>

-    public sealed class EnumValueDescriptor : IndexedDescriptorBase<EnumValueDescriptorProto, EnumValueOptions>                                              

+    public sealed class EnumValueDescriptor : DescriptorBase                                            

     {

         private readonly EnumDescriptor enumDescriptor;

+        private readonly EnumValueDescriptorProto proto;

 

         internal EnumValueDescriptor(EnumValueDescriptorProto proto, FileDescriptor file,

                                      EnumDescriptor parent, int index)

-            : base(proto, file, parent.FullName + "." + proto.Name, index)

+            : base(file, parent.FullName + "." + proto.Name, index)

         {

+            this.proto = proto;

             enumDescriptor = parent;

             file.DescriptorPool.AddSymbol(this);

             file.DescriptorPool.AddEnumValueByNumber(this);

         }

 

-        public int Number

-        {

-            get { return Proto.Number; }

-        }

+        internal EnumValueDescriptorProto Proto { get { return proto; } }

+        

+        public override string Name { get { return proto.Name; } }

 

-        public EnumDescriptor EnumDescriptor

-        {

-            get { return enumDescriptor; }

-        }

+        public int Number { get { return Proto.Number; } }

+

+        public EnumDescriptor EnumDescriptor { get { return enumDescriptor; } }

     }

 }
\ No newline at end of file
diff --git a/csharp/src/ProtocolBuffers/Descriptors/FieldDescriptor.cs b/csharp/src/ProtocolBuffers/Descriptors/FieldDescriptor.cs
index 2f2c580..7af69bb 100644
--- a/csharp/src/ProtocolBuffers/Descriptors/FieldDescriptor.cs
+++ b/csharp/src/ProtocolBuffers/Descriptors/FieldDescriptor.cs
@@ -38,21 +38,20 @@
     /// <summary>

     /// Descriptor for a field or extension within a message in a .proto file.

     /// </summary>

-    public sealed class FieldDescriptor : IndexedDescriptorBase<FieldDescriptorProto, FieldOptions>,

-                                          IComparable<FieldDescriptor>

+    public sealed class FieldDescriptor : DescriptorBase, IComparable<FieldDescriptor>

     {

+        private readonly FieldDescriptorProto proto;

         private EnumDescriptor enumType;

         private MessageDescriptor messageType;

-        private MessageDescriptor containingType;

-        private OneofDescriptor containingOneof;

+        private readonly MessageDescriptor containingType;

+        private readonly OneofDescriptor containingOneof;

         private FieldType fieldType;

 

-        private readonly object optionsLock = new object();

-

         internal FieldDescriptor(FieldDescriptorProto proto, FileDescriptor file,

                                  MessageDescriptor parent, int index)

-            : base(proto, file, ComputeFullName(file, parent, proto.Name), index)

+            : base(file, file.ComputeFullName(parent, proto.Name), index)

         {

+            this.proto = proto;

             if (proto.Type != 0)

             {

                 fieldType = GetFieldTypeFromProtoType(proto.Type);

@@ -64,7 +63,8 @@
                                                         "Field numbers must be positive integers.");

             }

             containingType = parent;

-            if (proto.OneofIndex != 0)

+            // OneofIndex "defaults" to -1 due to a hack in FieldDescriptor.OnConstruction.

+            if (proto.OneofIndex != -1)

             {

                 if (proto.OneofIndex < 0 || proto.OneofIndex >= parent.Proto.OneofDecl.Count)

                 {

@@ -72,13 +72,19 @@
                         "FieldDescriptorProto.oneof_index is out of range for type " + parent.Name);

                 }

                 containingOneof = parent.Oneofs[proto.OneofIndex];

-                containingOneof.fieldCount ++;

             }

 

             file.DescriptorPool.AddSymbol(this);

         }

 

         /// <summary>

+        /// The brief name of the descriptor's target.

+        /// </summary>

+        public override string Name { get { return proto.Name; } }

+

+        internal FieldDescriptorProto Proto { get { return proto; } }

+        

+        /// <summary>

         /// Maps a field type as included in the .proto file to a FieldType.

         /// </summary>

         private static FieldType GetFieldTypeFromProtoType(FieldDescriptorProto.Types.Type type)

@@ -131,9 +137,14 @@
             get { return Proto.Label == FieldDescriptorProto.Types.Label.LABEL_REPEATED; }

         }

 

+        public bool IsMap

+        {

+            get { return fieldType == FieldType.Message && messageType.Proto.Options != null && messageType.Proto.Options.MapEntry; }

+        }

+

         public bool IsPacked

         {

-            get { return Proto.Options.Packed; }

+            get { return Proto.Options != null && Proto.Options.Packed; }

         }        

 

         /// <summary>

@@ -273,7 +284,7 @@
 

             File.DescriptorPool.AddFieldByNumber(this);

 

-            if (containingType != null && containingType.Options != null && containingType.Options.MessageSetWireFormat)

+            if (containingType != null && containingType.Proto.Options != null && containingType.Proto.Options.MessageSetWireFormat)

             {

                 throw new DescriptorValidationException(this, "MessageSet format is not supported.");

             }

diff --git a/csharp/src/ProtocolBuffers/Descriptors/FileDescriptor.cs b/csharp/src/ProtocolBuffers/Descriptors/FileDescriptor.cs
index 7da14a5..9d0bdfd 100644
--- a/csharp/src/ProtocolBuffers/Descriptors/FileDescriptor.cs
+++ b/csharp/src/ProtocolBuffers/Descriptors/FileDescriptor.cs
@@ -43,7 +43,7 @@
     /// IDescriptor is implemented such that the File property returns this descriptor,

     /// and the FullName is the same as the Name.

     /// </summary>

-    public sealed class FileDescriptor : IDescriptor<FileDescriptorProto>

+    public sealed class FileDescriptor : IDescriptor

     {

         private readonly FileDescriptorProto proto;

         private readonly IList<MessageDescriptor> messageTypes;

@@ -88,6 +88,22 @@
         }

 

         /// <summary>

+        /// Computes the full name of a descriptor within this file, with an optional parent message.

+        /// </summary>

+        internal string ComputeFullName(MessageDescriptor parent, string name)

+        {

+            if (parent != null)

+            {

+                return parent.FullName + "." + name;

+            }

+            if (Package.Length > 0)

+            {

+                return Package + "." + name;

+            }

+            return name;

+        }

+

+        /// <summary>

         /// Extracts public dependencies from direct dependencies. This is a static method despite its

         /// first parameter, as the value we're in the middle of constructing is only used for exceptions.

         /// </summary>

@@ -127,20 +143,12 @@
         /// <value>

         /// The descriptor in its protocol message representation.

         /// </value>

-        public FileDescriptorProto Proto

+        internal FileDescriptorProto Proto

         {

             get { return proto; }

         }

 

         /// <value>

-        /// The <see cref="DescriptorProtos.FileOptions" /> defined in <c>descriptor.proto</c>.

-        /// </value>

-        public FileOptions Options

-        {

-            get { return proto.Options; }

-        }

-

-        /// <value>

         /// The file name.

         /// </value>

         public string Name

@@ -214,14 +222,6 @@
         }

 

         /// <value>

-        /// Protocol buffer describing this descriptor.

-        /// </value>

-        IMessage IDescriptor.Proto

-        {

-            get { return Proto; }

-        }

-

-        /// <value>

         /// Pool containing symbol descriptors.

         /// </value>

         internal DescriptorPool DescriptorPool

@@ -255,22 +255,7 @@
             }

             return null;

         }

-

-        /// <summary>

-        /// Builds a FileDescriptor from its protocol buffer representation.

-        /// </summary>

-        /// <param name="proto">The protocol message form of the FileDescriptor.</param>

-        /// <param name="dependencies">FileDescriptors corresponding to all of the

-        /// 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>

-        /// <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>

-        public static FileDescriptor BuildFrom(FileDescriptorProto proto, FileDescriptor[] dependencies)

-        {

-            return BuildFrom(proto, dependencies, false);

-        }

-

+        

         /// <summary>

         /// Builds a FileDescriptor from its protocol buffer representation.

         /// </summary>

@@ -336,33 +321,8 @@
             }

         }

 

-        /// <summary>

-        /// This method is to be called by generated code only.  It is equivalent

-        /// to BuildFrom except that the FileDescriptorProto is encoded in

-        /// protocol buffer wire format. This overload is maintained for backward

-        /// compatibility with source code generated before the custom options were available

-        /// (and working).

-        /// </summary>

-        public static FileDescriptor InternalBuildGeneratedFileFrom(byte[] descriptorData, FileDescriptor[] dependencies)

-        {

-            return InternalBuildGeneratedFileFrom(descriptorData, dependencies, x => { });

-        }

-

-        /// <summary>

-        /// This delegate should be used by generated code only. When calling

-        /// FileDescriptor.InternalBuildGeneratedFileFrom, the caller can provide

-        /// a callback which assigns the global variables defined in the generated code

-        /// which point at parts of the FileDescriptor. The callback returns an

-        /// Extension Registry which contains any extensions which might be used in

-        /// the descriptor - that is, extensions of the various "Options" messages defined

-        /// in descriptor.proto. The callback may also return null to indicate that

-        /// no extensions are used in the descriptor.

-        /// </summary>

-        public delegate void InternalDescriptorAssigner(FileDescriptor descriptor);

-

         public static FileDescriptor InternalBuildGeneratedFileFrom(byte[] descriptorData,

-                                                                    FileDescriptor[] dependencies,

-                                                                    InternalDescriptorAssigner descriptorAssigner)

+                                                                    FileDescriptor[] dependencies)

         {

             FileDescriptorProto proto;

             try

@@ -374,20 +334,16 @@
                 throw new ArgumentException("Failed to parse protocol buffer descriptor for generated code.", e);

             }

 

-            FileDescriptor result;

             try

             {

                 // When building descriptors for generated code, we allow unknown

                 // dependencies by default.

-                result = BuildFrom(proto, dependencies, true);

+                return BuildFrom(proto, dependencies, true);

             }

             catch (DescriptorValidationException e)

             {

                 throw new ArgumentException("Invalid embedded descriptor for \"" + proto.Name + "\".", e);

             }

-

-            descriptorAssigner(result);

-            return result;

         }

         

         public override string ToString()

diff --git a/csharp/src/ProtocolBuffers/Descriptors/IDescriptor.cs b/csharp/src/ProtocolBuffers/Descriptors/IDescriptor.cs
index 2c2db12..92c6d46 100644
--- a/csharp/src/ProtocolBuffers/Descriptors/IDescriptor.cs
+++ b/csharp/src/ProtocolBuffers/Descriptors/IDescriptor.cs
@@ -33,23 +33,12 @@
 namespace Google.Protobuf.Descriptors

 {

     /// <summary>

-    /// The non-generic form of the IDescriptor interface. Useful for describing a general

-    /// descriptor.

+    /// Interface implemented by all descriptor types.

     /// </summary>

     public interface IDescriptor

     {

         string Name { get; }

         string FullName { get; }

         FileDescriptor File { get; }

-        IMessage Proto { get; }

-    }

-

-    /// <summary>

-    /// Strongly-typed form of the IDescriptor interface.

-    /// </summary>

-    /// <typeparam name="TProto">Protocol buffer type underlying this descriptor type</typeparam>

-    internal interface IDescriptor<TProto> : IDescriptor where TProto : IMessage

-    {

-        new TProto Proto { get; }

-    }

+    }    

 }
\ No newline at end of file
diff --git a/csharp/src/ProtocolBuffers/Descriptors/IndexedDescriptorBase.cs b/csharp/src/ProtocolBuffers/Descriptors/IndexedDescriptorBase.cs
deleted file mode 100644
index 6c51572..0000000
--- a/csharp/src/ProtocolBuffers/Descriptors/IndexedDescriptorBase.cs
+++ /dev/null
@@ -1,65 +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 Google.Protobuf.DescriptorProtos;

-

-namespace Google.Protobuf.Descriptors

-{

-    /// <summary>

-    /// Base class for descriptors which are also indexed. This is all of them other than

-    /// <see cref="FileDescriptor" />.

-    /// </summary>

-    public abstract class IndexedDescriptorBase<TProto, TOptions> : DescriptorBase<TProto, TOptions>

-        where TProto : IMessage<TProto>, IDescriptorProto<TOptions>

-    {

-        private readonly int index;

-

-        protected IndexedDescriptorBase(TProto proto, FileDescriptor file, string fullName, int index)

-            : base(proto, file, fullName)

-        {

-            this.index = index;

-        }

-

-        /// <value>

-        /// The index of this descriptor within its parent descriptor. 

-        /// </value>

-        /// <remarks>

-        /// This returns the index of this descriptor within its parent, for

-        /// this descriptor's type. (There can be duplicate values for different

-        /// types, e.g. one enum type with index 0 and one message type with index 0.)

-        /// </remarks>

-        public int Index

-        {

-            get { return index; }

-        }

-    }

-}
\ No newline at end of file
diff --git a/csharp/src/ProtocolBuffers/Descriptors/MessageDescriptor.cs b/csharp/src/ProtocolBuffers/Descriptors/MessageDescriptor.cs
index cbf4c0f..e65e8bb 100644
--- a/csharp/src/ProtocolBuffers/Descriptors/MessageDescriptor.cs
+++ b/csharp/src/ProtocolBuffers/Descriptors/MessageDescriptor.cs
@@ -39,8 +39,9 @@
     /// <summary>

     /// Describes a message type.

     /// </summary>

-    public sealed class MessageDescriptor : IndexedDescriptorBase<DescriptorProto, MessageOptions>

+    public sealed class MessageDescriptor : DescriptorBase

     {

+        private readonly DescriptorProto proto;

         private readonly MessageDescriptor containingType;

         private readonly IList<MessageDescriptor> nestedTypes;

         private readonly IList<EnumDescriptor> enumTypes;

@@ -48,8 +49,9 @@
         private readonly IList<OneofDescriptor> oneofs;

         

         internal MessageDescriptor(DescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int typeIndex)

-            : base(proto, file, ComputeFullName(file, parent, proto.Name), typeIndex)

+            : base(file, file.ComputeFullName(parent, proto.Name), typeIndex)

         {

+            this.proto = proto;

             containingType = parent;

 

             oneofs = DescriptorUtil.ConvertAndMakeReadOnly(proto.OneofDecl,

@@ -68,23 +70,16 @@
             fields = DescriptorUtil.ConvertAndMakeReadOnly(proto.Field,

                                                            (field, index) =>

                                                            new FieldDescriptor(field, file, this, index));

-

-            for (int i = 0; i < proto.OneofDecl.Count; i++)

-            {

-                oneofs[i].fields = new FieldDescriptor[oneofs[i].FieldCount];

-                oneofs[i].fieldCount = 0;

-            }

-            for (int i = 0; i< proto.Field.Count; i++)

-            {

-                OneofDescriptor oneofDescriptor = fields[i].ContainingOneof;

-                if (oneofDescriptor != null)

-                {

-                    oneofDescriptor.fields[oneofDescriptor.fieldCount++] = fields[i];

-                }

-            }

             file.DescriptorPool.AddSymbol(this);

         }

 

+        /// <summary>

+        /// The brief name of the descriptor's target.

+        /// </summary>

+        public override string Name { get { return proto.Name; } }

+

+        internal DescriptorProto Proto { get { return proto; } }

+

         /// <value>

         /// If this is a nested type, get the outer descriptor, otherwise null.

         /// </value>

@@ -144,7 +139,7 @@
 

         /// <summary>

         /// Finds a nested descriptor by name. The is valid for fields, nested

-        /// message types and enums.

+        /// message types, oneofs and enums.

         /// </summary>

         /// <param name="name">The unqualified name of the descriptor, e.g. "Foo"</param>

         /// <returns>The descriptor, or null if not found.</returns>

@@ -171,32 +166,8 @@
 

             foreach (OneofDescriptor oneof in oneofs)

             {

-                // TODO(jonskeet): Do we need to do this?

-                // oneof.C

+                oneof.CrossLink();

             }

-        }

-

-        /// <summary>

-        /// See FileDescriptor.ReplaceProto

-        /// </summary>

-        internal override void ReplaceProto(DescriptorProto newProto)

-        {

-            base.ReplaceProto(newProto);

-

-            for (int i = 0; i < nestedTypes.Count; i++)

-            {

-                nestedTypes[i].ReplaceProto(newProto.NestedType[i]);

-            }

-

-            for (int i = 0; i < enumTypes.Count; i++)

-            {

-                enumTypes[i].ReplaceProto(newProto.EnumType[i]);

-            }

-

-            for (int i = 0; i < fields.Count; i++)

-            {

-                fields[i].ReplaceProto(newProto.Field[i]);

-            }

-        }

+        }        

     }

 }
\ No newline at end of file
diff --git a/csharp/src/ProtocolBuffers/Descriptors/MethodDescriptor.cs b/csharp/src/ProtocolBuffers/Descriptors/MethodDescriptor.cs
index 6a4ad4e..7d4a6f4 100644
--- a/csharp/src/ProtocolBuffers/Descriptors/MethodDescriptor.cs
+++ b/csharp/src/ProtocolBuffers/Descriptors/MethodDescriptor.cs
@@ -37,8 +37,9 @@
     /// <summary>

     /// Describes a single method in a service.

     /// </summary>

-    public sealed class MethodDescriptor : IndexedDescriptorBase<MethodDescriptorProto, MethodOptions>

+    public sealed class MethodDescriptor : DescriptorBase

     {

+        private readonly MethodDescriptorProto proto;

         private readonly ServiceDescriptor service;

         private MessageDescriptor inputType;

         private MessageDescriptor outputType;

@@ -46,35 +47,34 @@
         /// <value>

         /// The service this method belongs to.

         /// </value>

-        public ServiceDescriptor Service

-        {

-            get { return service; }

-        }

+        public ServiceDescriptor Service { get { return service; } }

 

         /// <value>

         /// The method's input type.

         /// </value>

-        public MessageDescriptor InputType

-        {

-            get { return inputType; }

-        }

+        public MessageDescriptor InputType { get { return inputType; } }

 

         /// <value>

         /// The method's input type.

         /// </value>

-        public MessageDescriptor OutputType

-        {

-            get { return outputType; }

-        }

+        public MessageDescriptor OutputType { get { return outputType; } }

 

         internal MethodDescriptor(MethodDescriptorProto proto, FileDescriptor file,

                                   ServiceDescriptor parent, int index)

-            : base(proto, file, parent.FullName + "." + proto.Name, index)

+            : base(file, parent.FullName + "." + proto.Name, index)

         {

+            this.proto = proto;

             service = parent;

             file.DescriptorPool.AddSymbol(this);

         }

 

+        internal MethodDescriptorProto Proto { get { return proto; } }

+

+        /// <summary>

+        /// The brief name of the descriptor's target.

+        /// </summary>

+        public override string Name { get { return proto.Name; } }

+

         internal void CrossLink()

         {

             IDescriptor lookup = File.DescriptorPool.LookupSymbol(Proto.InputType, this);

diff --git a/csharp/src/ProtocolBuffers/Descriptors/OneofDescriptor.cs b/csharp/src/ProtocolBuffers/Descriptors/OneofDescriptor.cs
index ab3b76e..8418948 100644
--- a/csharp/src/ProtocolBuffers/Descriptors/OneofDescriptor.cs
+++ b/csharp/src/ProtocolBuffers/Descriptors/OneofDescriptor.cs
@@ -31,48 +31,49 @@
 #endregion

 

 using System.Collections.Generic;

+using System.Collections.ObjectModel;

 using Google.Protobuf.DescriptorProtos;

 

 namespace Google.Protobuf.Descriptors

 {

-    public sealed class OneofDescriptor

+    public sealed class OneofDescriptor : DescriptorBase

     {

-        private int index;

-        private OneofDescriptorProto proto;

-        private FileDescriptor file;

+        private readonly OneofDescriptorProto proto;

         private MessageDescriptor containingType;

-        internal int fieldCount;

-        internal IList<FieldDescriptor> fields;

+        private IList<FieldDescriptor> fields;

 

-        internal OneofDescriptor(OneofDescriptorProto proto, FileDescriptor file,

-                                 MessageDescriptor parent, int index)

+        internal OneofDescriptor(OneofDescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int index)

+            : base(file, file.ComputeFullName(parent, proto.Name), index)

         {

             this.proto = proto;

-            this.file = file;

-            this.index = index;

-

             containingType = parent;

-            fieldCount = 0;

+

+            file.DescriptorPool.AddSymbol(this);

         }

 

-        public int Index

-        {

-            get { return index; }

-        }

+        /// <summary>

+        /// The brief name of the descriptor's target.

+        /// </summary>

+        public override string Name { get { return proto.Name; } }

 

         public MessageDescriptor ContainingType

         {

             get { return containingType; }

         }

 

-        public int FieldCount

-        {

-            get { return fieldCount; }

-        }

+        public IList<FieldDescriptor> Fields { get { return fields; } }

 

-        public FieldDescriptor Field(int index)

+        internal void CrossLink()

         {

-            return fields[index];

+            List<FieldDescriptor> fieldCollection = new List<FieldDescriptor>();

+            foreach (var field in ContainingType.Fields)

+            {

+                if (field.ContainingOneof == this)

+                {

+                    fieldCollection.Add(field);

+                }

+            }

+            fields = new ReadOnlyCollection<FieldDescriptor>(fieldCollection);

         }

     }

 }

diff --git a/csharp/src/ProtocolBuffers/Descriptors/PackageDescriptor.cs b/csharp/src/ProtocolBuffers/Descriptors/PackageDescriptor.cs
index 9af677d..18adc9e 100644
--- a/csharp/src/ProtocolBuffers/Descriptors/PackageDescriptor.cs
+++ b/csharp/src/ProtocolBuffers/Descriptors/PackageDescriptor.cs
@@ -37,7 +37,7 @@
     /// just as placeholders so that someone cannot define, say, a message type

     /// that has the same name as an existing package.

     /// </summary>

-    internal sealed class PackageDescriptor : IDescriptor<IMessage>

+    internal sealed class PackageDescriptor : IDescriptor

     {

         private readonly string name;

         private readonly string fullName;

@@ -50,11 +50,6 @@
             this.name = name;

         }

 

-        public IMessage Proto

-        {

-            get { return file.Proto; }

-        }

-

         public string Name

         {

             get { return name; }

diff --git a/csharp/src/ProtocolBuffers/Descriptors/ServiceDescriptor.cs b/csharp/src/ProtocolBuffers/Descriptors/ServiceDescriptor.cs
index ef712b4..2556e27 100644
--- a/csharp/src/ProtocolBuffers/Descriptors/ServiceDescriptor.cs
+++ b/csharp/src/ProtocolBuffers/Descriptors/ServiceDescriptor.cs
@@ -39,19 +39,28 @@
     /// <summary>

     /// Describes a service type.

     /// </summary>

-    public sealed class ServiceDescriptor : IndexedDescriptorBase<ServiceDescriptorProto, ServiceOptions>

+    public sealed class ServiceDescriptor : DescriptorBase

     {

+        private readonly ServiceDescriptorProto proto;

         private readonly IList<MethodDescriptor> methods;

 

-        public ServiceDescriptor(ServiceDescriptorProto proto, FileDescriptor file, int index)

-            : base(proto, file, ComputeFullName(file, null, proto.Name), index)

+        internal ServiceDescriptor(ServiceDescriptorProto proto, FileDescriptor file, int index)

+            : base(file, file.ComputeFullName(null, proto.Name), index)

         {

+            this.proto = proto;

             methods = DescriptorUtil.ConvertAndMakeReadOnly(proto.Method,

                                                             (method, i) => new MethodDescriptor(method, file, this, i));

 

             file.DescriptorPool.AddSymbol(this);

         }

 

+        /// <summary>

+        /// The brief name of the descriptor's target.

+        /// </summary>

+        public override string Name { get { return proto.Name; } }

+

+        internal ServiceDescriptorProto Proto { get { return proto; } }

+

         /// <value>

         /// An unmodifiable list of methods in this service.

         /// </value>

@@ -77,14 +86,5 @@
                 method.CrossLink();

             }

         }

-

-        internal override void ReplaceProto(ServiceDescriptorProto newProto)

-        {

-            base.ReplaceProto(newProto);

-            for (int i = 0; i < methods.Count; i++)

-            {

-                methods[i].ReplaceProto(newProto.Method[i]);

-            }

-        }

     }

 }
\ No newline at end of file
diff --git a/csharp/src/ProtocolBuffers/FieldAccess/FieldAccessorBase.cs b/csharp/src/ProtocolBuffers/FieldAccess/FieldAccessorBase.cs
index 73d777b..2a3e5b8 100644
--- a/csharp/src/ProtocolBuffers/FieldAccess/FieldAccessorBase.cs
+++ b/csharp/src/ProtocolBuffers/FieldAccess/FieldAccessorBase.cs
@@ -32,34 +32,37 @@
 
 using System;
 using System.Reflection;
+using Google.Protobuf.Descriptors;
 
 namespace Google.Protobuf.FieldAccess
 {
     /// <summary>
     /// Base class for field accessors.
     /// </summary>
-    /// <typeparam name="T">Type of message containing the field</typeparam>
-    internal abstract class FieldAccessorBase<T> : IFieldAccessor<T> where T : IMessage<T>
+    internal abstract class FieldAccessorBase : IFieldAccessor
     {
-        private readonly Func<T, object> getValueDelegate;
+        private readonly Func<object, object> getValueDelegate;
+        private readonly FieldDescriptor descriptor;
 
-        internal FieldAccessorBase(string name)
+        internal FieldAccessorBase(Type type, string propertyName, FieldDescriptor descriptor)
         {
-            PropertyInfo property = typeof(T).GetProperty(name);
+            PropertyInfo property = type.GetProperty(propertyName);
             if (property == null || !property.CanRead)
             {
                 throw new ArgumentException("Not all required properties/methods available");
             }
-            getValueDelegate = ReflectionUtil.CreateUpcastDelegate<T>(property.GetGetMethod());
+            this.descriptor = descriptor;
+            getValueDelegate = ReflectionUtil.CreateFuncObjectObject(property.GetGetMethod());
         }
 
-        public object GetValue(T message)
+        public FieldDescriptor Descriptor { get { return descriptor; } }
+
+        public object GetValue(object message)
         {
             return getValueDelegate(message);
         }
 
-        public abstract bool HasValue(T message);
-        public abstract void Clear(T message);
-        public abstract void SetValue(T message, object value);
+        public abstract void Clear(object message);
+        public abstract void SetValue(object message, object value);
     }
 }
diff --git a/csharp/src/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs b/csharp/src/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs
index 6379ff2..57ea9c8 100644
--- a/csharp/src/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs
+++ b/csharp/src/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs
@@ -31,6 +31,7 @@
 #endregion

 

 using System;

+using System.Collections.ObjectModel;

 using Google.Protobuf.Descriptors;

 

 namespace Google.Protobuf.FieldAccess

@@ -38,34 +39,43 @@
     /// <summary>

     /// Provides access to fields in generated messages via reflection.

     /// </summary>

-    public sealed class FieldAccessorTable<T> where T : IMessage<T>

+    public sealed class FieldAccessorTable

     {

-        private readonly IFieldAccessor<T>[] accessors;

+        private readonly ReadOnlyCollection<IFieldAccessor> accessors;

         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(MessageDescriptor descriptor, string[] propertyNames)

+        public FieldAccessorTable(Type type, MessageDescriptor descriptor, string[] propertyNames)

         {

             this.descriptor = descriptor;

-            accessors = new IFieldAccessor<T>[descriptor.Fields.Count];

-            bool supportFieldPresence = descriptor.File.Syntax == FileDescriptor.ProtoSyntax.Proto2;

-            for (int i = 0; i < accessors.Length; i++)

+            var accessorsArray = new IFieldAccessor[descriptor.Fields.Count];

+            for (int i = 0; i < accessorsArray.Length; i++)

             {

                 var field = descriptor.Fields[i];

                 var name = propertyNames[i];

-                accessors[i] = field.IsRepeated

-                    ? (IFieldAccessor<T>) new RepeatedFieldAccessor<T>(propertyNames[i])

-                    : new SingleFieldAccessor<T>(field, name, supportFieldPresence);

+                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);

             // TODO(jonskeet): Oneof support

         }

 

-        internal IFieldAccessor<T> this[int fieldNumber]

+        // 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 IFieldAccessor this[int fieldNumber]

         {

             get

             {

@@ -74,7 +84,7 @@
             }

         }

 

-        internal IFieldAccessor<T> this[FieldDescriptor field]

+        internal IFieldAccessor this[FieldDescriptor field]

         {

             get

             {

diff --git a/csharp/src/ProtocolBuffers/FieldAccess/IFieldAccessor.cs b/csharp/src/ProtocolBuffers/FieldAccess/IFieldAccessor.cs
index 6183854..77e7146 100644
--- a/csharp/src/ProtocolBuffers/FieldAccess/IFieldAccessor.cs
+++ b/csharp/src/ProtocolBuffers/FieldAccess/IFieldAccessor.cs
@@ -30,39 +30,41 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

 #endregion

 

+using Google.Protobuf.Descriptors;

+

 namespace Google.Protobuf.FieldAccess

 {

     /// <summary>

-    /// Allows fields to be reflectively accessed in a smart manner.

-    /// The property descriptors for each field are created once and then cached.

-    /// In addition, this interface holds knowledge of repeated fields, builders etc.

+    /// Allows fields to be reflectively accessed.

     /// </summary>

-    internal interface IFieldAccessor<T> where T : IMessage<T>

+    public interface IFieldAccessor

     {

         /// <summary>

-        /// Indicates whether the specified message contains the field. For primitive fields

-        /// declared in proto3-syntax messages, this simply checks whether the value is the default one.

+        /// Returns the descriptor associated with this field.

         /// </summary>

-        /// <exception cref="InvalidOperationException">The field is a repeated field, or a single primitive field.</exception>

-        bool HasValue(T message);

+        FieldDescriptor Descriptor { get; }

 

         /// <summary>

         /// Clears the field in the specified message. (For repeated fields,

         /// this clears the list.)

         /// </summary>

-        void Clear(T message);

+        void Clear(object message);

 

         /// <summary>

         /// Fetches the field value. For repeated values, this will be an

-        /// <see cref="IList"/> implementation.

+        /// <see cref="IList"/> implementation. For map values, this will be an

+        /// <see cref="IDictionary"/> implementation.

         /// </summary>

-        object GetValue(T message);

+        object GetValue(object message);

 

         /// <summary>

-        /// Mutator for single fields only. (Repeated fields must be mutated

-        /// by fetching the list, then mutating that.)

+        /// Mutator for single "simple" fields only.

         /// </summary>

-        /// <exception cref="InvalidOperationException">The field is a repeated field.</exception>

-        void SetValue(T message, object value);

+        /// <remarks>

+        /// Repeated fields are mutated by fetching the value and manipulating it as a list.

+        /// Map fields are mutated by fetching the value and manipulating it as a dictionary.

+        /// </remarks>

+        /// <exception cref="InvalidOperationException">The field is not a "simple" field, or the message is frozen.</exception>

+        void SetValue(object message, object value);

     }

 }
\ No newline at end of file
diff --git a/csharp/src/ProtocolBuffers/DescriptorProtos/IDescriptorProto.cs b/csharp/src/ProtocolBuffers/FieldAccess/MapFieldAccessor.cs
similarity index 67%
rename from csharp/src/ProtocolBuffers/DescriptorProtos/IDescriptorProto.cs
rename to csharp/src/ProtocolBuffers/FieldAccess/MapFieldAccessor.cs
index c0f2742..100dbb3 100644
--- a/csharp/src/ProtocolBuffers/DescriptorProtos/IDescriptorProto.cs
+++ b/csharp/src/ProtocolBuffers/FieldAccess/MapFieldAccessor.cs
@@ -1,53 +1,59 @@
-#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

-

-namespace Google.Protobuf.DescriptorProtos

-{

-    /// <summary>

-    /// Interface implemented by all DescriptorProtos. The generator doesn't

-    /// emit the interface implementation claim, so PartialClasses.cs contains

-    /// partial class declarations for each of them.

-    /// </summary>

-    /// <typeparam name="TOptions">The associated options protocol buffer type</typeparam>

-    public interface IDescriptorProto<TOptions>

-    {

-        /// <summary>

-        /// The brief name of the descriptor's target.

-        /// </summary>

-        string Name { get; }

-

-        /// <summary>

-        /// The options for this descriptor.

-        /// </summary>

-        TOptions Options { get; }

-    }

-}
\ No newline at end of file
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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;
+using Google.Protobuf.Descriptors;
+
+namespace Google.Protobuf.FieldAccess
+{
+    /// <summary>
+    /// Accessor for map fields.
+    /// </summary>
+    internal sealed class MapFieldAccessor : FieldAccessorBase
+    {
+        internal MapFieldAccessor(Type type, string propertyName, FieldDescriptor descriptor) : base(type, propertyName, descriptor)
+        {
+        }
+
+        public override void Clear(object message)
+        {
+            IDictionary list = (IDictionary) GetValue(message);
+            list.Clear();
+        }
+
+        public override void SetValue(object message, object value)
+        {
+            throw new InvalidOperationException("SetValue is not implemented for map fields");
+        }
+    }
+}
diff --git a/csharp/src/ProtocolBuffers/FieldAccess/ReflectionUtil.cs b/csharp/src/ProtocolBuffers/FieldAccess/ReflectionUtil.cs
index 29399b0..d305392 100644
--- a/csharp/src/ProtocolBuffers/FieldAccess/ReflectionUtil.cs
+++ b/csharp/src/ProtocolBuffers/FieldAccess/ReflectionUtil.cs
@@ -31,6 +31,7 @@
 #endregion

 

 using System;

+using System.Linq.Expressions;

 using System.Reflection;

 

 namespace Google.Protobuf.FieldAccess

@@ -51,101 +52,42 @@
         internal static readonly Type[] EmptyTypes = new Type[0];

 

         /// <summary>

-        /// Creates a delegate which will execute the given method and then return

-        /// the result as an object.

+        /// Creates a delegate which will cast the argument to the appropriate method target type,

+        /// call the method on it, then convert the result to object.

         /// </summary>

-        public static Func<T, object> CreateUpcastDelegate<T>(MethodInfo method)

+        internal static Func<object, object> CreateFuncObjectObject(MethodInfo method)

         {

-            // The tricky bit is invoking CreateCreateUpcastDelegateImpl with the right type parameters

-            MethodInfo openImpl = typeof(ReflectionUtil).GetMethod("CreateUpcastDelegateImpl");

-            MethodInfo closedImpl = openImpl.MakeGenericMethod(typeof(T), method.ReturnType);

-            return (Func<T, object>) closedImpl.Invoke(null, new object[] {method});

+            ParameterExpression parameter = Expression.Parameter(typeof(object), "p");

+            Expression downcast = Expression.Convert(parameter, method.DeclaringType);

+            Expression call = Expression.Call(downcast, method);

+            Expression upcast = Expression.Convert(call, typeof(object));

+            return Expression.Lambda<Func<object, object>>(upcast, parameter).Compile();

+        }

+        

+        /// <summary>

+        /// Creates a delegate which will execute the given method after casting the first argument to

+        /// the target type of the method, and the second argument to the first parameter type of the method.

+        /// </summary>

+        internal static Action<object, object> CreateActionObjectObject(MethodInfo method)

+        {

+            ParameterExpression targetParameter = Expression.Parameter(typeof(object), "target");

+            ParameterExpression argParameter = Expression.Parameter(typeof(object), "arg");

+            Expression castTarget = Expression.Convert(targetParameter, method.DeclaringType);

+            Expression castArgument = Expression.Convert(argParameter, method.GetParameters()[0].ParameterType);

+            Expression call = Expression.Call(castTarget, method, castArgument);

+            return Expression.Lambda<Action<object, object>>(call, targetParameter, argParameter).Compile();

         }

 

         /// <summary>

-        /// Method used solely for implementing CreateUpcastDelegate. Public to avoid trust issues

-        /// in low-trust scenarios.

+        /// Creates a delegate which will execute the given method after casting the first argument to

+        /// the target type of the method.

         /// </summary>

-        public static Func<TSource, object> CreateUpcastDelegateImpl<TSource, TResult>(MethodInfo method)

+        internal static Action<object> CreateActionObject(MethodInfo method)

         {

-            // Convert the reflection call into an open delegate, i.e. instead of calling x.Method()

-            // we'll call getter(x).

-            Func<TSource, TResult> getter = ReflectionUtil.CreateDelegateFunc<TSource, TResult>(method);

-

-            // Implicit upcast to object (within the delegate)

-            return source => getter(source);

-        }

-

-        /// <summary>

-        /// Creates a delegate which will execute the given method after casting the parameter

-        /// down from object to the required parameter type.

-        /// </summary>

-        public static Action<T, object> CreateDowncastDelegate<T>(MethodInfo method)

-        {

-            MethodInfo openImpl = typeof(ReflectionUtil).GetMethod("CreateDowncastDelegateImpl");

-            MethodInfo closedImpl = openImpl.MakeGenericMethod(typeof(T), method.GetParameters()[0].ParameterType);

-            return (Action<T, object>) closedImpl.Invoke(null, new object[] {method});

-        }

-

-        public static Action<TSource, object> CreateDowncastDelegateImpl<TSource, TParam>(MethodInfo method)

-        {

-            // Convert the reflection call into an open delegate, i.e. instead of calling x.Method(y) we'll

-            // call Method(x, y)

-            Action<TSource, TParam> call = ReflectionUtil.CreateDelegateAction<TSource, TParam>(method);

-

-            return (source, parameter) => call(source, (TParam) parameter);

-        }

-

-        /// <summary>

-        /// Creates a delegate which will execute the given method after casting the parameter

-        /// down from object to the required parameter type.

-        /// </summary>

-        public static Action<T, object> CreateDowncastDelegateIgnoringReturn<T>(MethodInfo method)

-        {

-            MethodInfo openImpl = typeof(ReflectionUtil).GetMethod("CreateDowncastDelegateIgnoringReturnImpl");

-            MethodInfo closedImpl = openImpl.MakeGenericMethod(typeof(T), method.GetParameters()[0].ParameterType,

-                                                               method.ReturnType);

-            return (Action<T, object>) closedImpl.Invoke(null, new object[] {method});

-        }

-

-        public static Action<TSource, object> CreateDowncastDelegateIgnoringReturnImpl<TSource, TParam, TReturn>(

-            MethodInfo method)

-        {

-            // Convert the reflection call into an open delegate, i.e. instead of calling x.Method(y) we'll

-            // call Method(x, y)

-            Func<TSource, TParam, TReturn> call = ReflectionUtil.CreateDelegateFunc<TSource, TParam, TReturn>(method);

-

-            return delegate(TSource source, object parameter) { call(source, (TParam) parameter); };

-        }

-

-        internal static Func<TResult> CreateDelegateFunc<TResult>(MethodInfo method)

-        {

-            object tdelegate = Delegate.CreateDelegate(typeof(Func<TResult>), null, method);

-            return (Func<TResult>)tdelegate;

-        }

-

-        internal static Func<T, TResult> CreateDelegateFunc<T, TResult>(MethodInfo method)

-        {

-            object tdelegate = Delegate.CreateDelegate(typeof(Func<T, TResult>), null, method);

-            return (Func<T, TResult>)tdelegate;

-        }

-

-        internal static Func<T1, T2, TResult> CreateDelegateFunc<T1, T2, TResult>(MethodInfo method)

-        {

-            object tdelegate = Delegate.CreateDelegate(typeof(Func<T1, T2, TResult>), null, method);

-            return (Func<T1, T2, TResult>)tdelegate;

-        }

-

-        internal static Action<T> CreateDelegateAction<T>(MethodInfo method)

-        {

-            object tdelegate = Delegate.CreateDelegate(typeof(Action<T>), null, method);

-            return (Action<T>)tdelegate;

-        }

-

-        internal static Action<T1, T2> CreateDelegateAction<T1, T2>(MethodInfo method)

-        {

-            object tdelegate = Delegate.CreateDelegate(typeof(Action<T1, T2>), null, method);

-            return (Action<T1, T2>)tdelegate;

+            ParameterExpression targetParameter = Expression.Parameter(typeof(object), "target");

+            Expression castTarget = Expression.Convert(targetParameter, method.DeclaringType);

+            Expression call = Expression.Call(castTarget, method);

+            return Expression.Lambda<Action<object>>(call, targetParameter).Compile();

         }

     }

 }
\ No newline at end of file
diff --git a/csharp/src/ProtocolBuffers/FieldAccess/RepeatedFieldAccessor.cs b/csharp/src/ProtocolBuffers/FieldAccess/RepeatedFieldAccessor.cs
index b12278f..8d7ecba 100644
--- a/csharp/src/ProtocolBuffers/FieldAccess/RepeatedFieldAccessor.cs
+++ b/csharp/src/ProtocolBuffers/FieldAccess/RepeatedFieldAccessor.cs
@@ -32,33 +32,28 @@
 
 using System;
 using System.Collections;
+using Google.Protobuf.Descriptors;
 
 namespace Google.Protobuf.FieldAccess
 {
     /// <summary>
     /// Accessor for repeated fields.
     /// </summary>
-    /// <typeparam name="T">The type of message containing the field.</typeparam>
-    internal sealed class RepeatedFieldAccessor<T> : FieldAccessorBase<T> where T : IMessage<T>
+    internal sealed class RepeatedFieldAccessor : FieldAccessorBase
     {
-        internal RepeatedFieldAccessor(string name) : base(name)
+        internal RepeatedFieldAccessor(Type type, string propertyName, FieldDescriptor descriptor) : base(type, propertyName, descriptor)
         {
         }
 
-        public override void Clear(T message)
+        public override void Clear(object message)
         {
             IList list = (IList) GetValue(message);
             list.Clear();
         }
 
-        public override bool HasValue(T message)
+        public override void SetValue(object message, object value)
         {
-            throw new NotImplementedException("HasValue is not implemented for repeated fields");
-        }
-
-        public override void SetValue(T message, object value)
-        {
-            throw new NotImplementedException("SetValue is not implemented for repeated fields");
+            throw new InvalidOperationException("SetValue is not implemented for repeated fields");
         }
 
     }
diff --git a/csharp/src/ProtocolBuffers/FieldAccess/SingleFieldAccessor.cs b/csharp/src/ProtocolBuffers/FieldAccess/SingleFieldAccessor.cs
index 7a8f726..cdc89e8 100644
--- a/csharp/src/ProtocolBuffers/FieldAccess/SingleFieldAccessor.cs
+++ b/csharp/src/ProtocolBuffers/FieldAccess/SingleFieldAccessor.cs
@@ -39,76 +39,46 @@
     /// <summary>
     /// Accessor for single fields.
     /// </summary>
-    /// <typeparam name="T">The type of message containing the field.</typeparam>
-    internal sealed class SingleFieldAccessor<T> : FieldAccessorBase<T> where T : IMessage<T>
+    internal sealed class SingleFieldAccessor : FieldAccessorBase
     {
         // All the work here is actually done in the constructor - it creates the appropriate delegates.
         // There are various cases to consider, based on the property type (message, string/bytes, or "genuine" primitive)
         // and proto2 vs proto3 for non-message types, as proto3 doesn't support "full" presence detection or default
         // values.
 
-        private readonly Action<T, object> setValueDelegate;
-        private readonly Action<T> clearDelegate;
-        private readonly Func<T, bool> hasValueDelegate;
+        private readonly Action<object, object> setValueDelegate;
+        private readonly Action<object> clearDelegate;
 
-        internal SingleFieldAccessor(FieldDescriptor descriptor, string name, bool supportsFieldPresence) : base(name)
+        internal SingleFieldAccessor(Type type, string propertyName, FieldDescriptor descriptor) : base(type, propertyName, descriptor)
         {
-            PropertyInfo property = typeof(T).GetProperty(name);
+            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");
             }
-            setValueDelegate = ReflectionUtil.CreateDowncastDelegate<T>(property.GetSetMethod());
+            setValueDelegate = ReflectionUtil.CreateActionObjectObject(property.GetSetMethod());
 
             var clrType = property.PropertyType;
+            
+            // TODO: What should clear on a oneof member do? Clear the oneof?
 
-            if (typeof(IMessage).IsAssignableFrom(clrType))
-            {
-                // Message types are simple - we only need to detect nullity.
-                clearDelegate = message => SetValue(message, null);
-                hasValueDelegate = message => GetValue(message) == null;
-            }
-
-            if (supportsFieldPresence)
-            {
-                // Proto2: we expect a HasFoo property and a ClearFoo method.
-                // For strings and byte arrays, setting the property to null would have the equivalent effect,
-                // but we generate the method for consistency, which makes this simpler.
-                PropertyInfo hasProperty = typeof(T).GetProperty("Has" + name);
-                MethodInfo clearMethod = typeof(T).GetMethod("Clear" + name);
-                if (hasProperty == null || clearMethod == null || !hasProperty.CanRead)
-                {
-                    throw new ArgumentException("Not all required properties/methods available");
-                }
-                hasValueDelegate = ReflectionUtil.CreateDelegateFunc<T, bool>(hasProperty.GetGetMethod());
-                clearDelegate = ReflectionUtil.CreateDelegateAction<T>(clearMethod);
-            }
-            else
-            {
-                /*
-                // TODO(jonskeet): Reimplement. We need a better way of working out default values.
-                // Proto3: for field detection, we just need the default value of the field (0, "", byte[0] etc)
-                // To clear a field, we set the value to that default.
-                object defaultValue = descriptor.DefaultValue;
-                hasValueDelegate = message => GetValue(message).Equals(defaultValue);
-                clearDelegate = message => SetValue(message, defaultValue);
-                */
-            }
+            // TODO: Validate that this is a reasonable single field? (Should be a value type, a message type, or string/ByteString.)
+            object defaultValue =
+                typeof(IMessage).IsAssignableFrom(clrType) ? null
+                : clrType == typeof(string) ? ""
+                : clrType == typeof(ByteString) ? ByteString.Empty
+                : Activator.CreateInstance(clrType);
+            clearDelegate = message => SetValue(message, defaultValue);
         }
 
-        public override bool HasValue(T message)
-        {
-            return hasValueDelegate(message);
-        }
-
-        public override void Clear(T message)
+        public override void Clear(object message)
         {
             clearDelegate(message);
         }
 
-        public override void SetValue(T message, object value)
+        public override void SetValue(object message, object value)
         {
             setValueDelegate(message, value);
         }
diff --git a/csharp/src/ProtocolBuffers/FieldCodec.cs b/csharp/src/ProtocolBuffers/FieldCodec.cs
index 2cebc1b..c72a3e7 100644
--- a/csharp/src/ProtocolBuffers/FieldCodec.cs
+++ b/csharp/src/ProtocolBuffers/FieldCodec.cs
@@ -68,12 +68,12 @@
 
         public static FieldCodec<uint> ForFixed32(uint tag)
         {
-            return new FieldCodec<uint>(input => input.ReadFixed32(), (output, value) => output.WriteFixed32(value), CodedOutputStream.ComputeFixed32Size, tag);
+            return new FieldCodec<uint>(input => input.ReadFixed32(), (output, value) => output.WriteFixed32(value), 4, tag);
         }
 
         public static FieldCodec<int> ForSFixed32(uint tag)
         {
-            return new FieldCodec<int>(input => input.ReadSFixed32(), (output, value) => output.WriteSFixed32(value), CodedOutputStream.ComputeSFixed32Size, tag);
+            return new FieldCodec<int>(input => input.ReadSFixed32(), (output, value) => output.WriteSFixed32(value), 4, tag);
         }
 
         public static FieldCodec<uint> ForUInt32(uint tag)
@@ -93,12 +93,12 @@
 
         public static FieldCodec<ulong> ForFixed64(uint tag)
         {
-            return new FieldCodec<ulong>(input => input.ReadFixed64(), (output, value) => output.WriteFixed64(value), CodedOutputStream.ComputeFixed64Size, tag);
+            return new FieldCodec<ulong>(input => input.ReadFixed64(), (output, value) => output.WriteFixed64(value), 8, tag);
         }
 
         public static FieldCodec<long> ForSFixed64(uint tag)
         {
-            return new FieldCodec<long>(input => input.ReadSFixed64(), (output, value) => output.WriteSFixed64(value), CodedOutputStream.ComputeSFixed64Size, tag);
+            return new FieldCodec<long>(input => input.ReadSFixed64(), (output, value) => output.WriteSFixed64(value), 8, tag);
         }
 
         public static FieldCodec<ulong> ForUInt64(uint tag)
diff --git a/csharp/src/ProtocolBuffers/IMessage.cs b/csharp/src/ProtocolBuffers/IMessage.cs
index 27bcc11..ad44668 100644
--- a/csharp/src/ProtocolBuffers/IMessage.cs
+++ b/csharp/src/ProtocolBuffers/IMessage.cs
@@ -40,12 +40,11 @@
     // TODO(jonskeet): Split these interfaces into separate files when we're happy with them.

 

     /// <summary>

-    /// Reflection support for a specific message type. message

+    /// Reflection support for a specific message type.

     /// </summary>

-    /// <typeparam name="T">The message type being reflected.</typeparam>

-    public interface IReflectedMessage<T> where T : IMessage<T>

+    public interface IReflectedMessage

     {

-        FieldAccessorTable<T> Fields { get; }

+        FieldAccessorTable Fields { get; }

         // TODO(jonskeet): Descriptor? Or a single property which has "all you need for reflection"?

     }

 

diff --git a/csharp/src/ProtocolBuffers/ProtocolBuffers.csproj b/csharp/src/ProtocolBuffers/ProtocolBuffers.csproj
index 1e7408e..aa4adcc 100644
--- a/csharp/src/ProtocolBuffers/ProtocolBuffers.csproj
+++ b/csharp/src/ProtocolBuffers/ProtocolBuffers.csproj
@@ -61,7 +61,6 @@
     <Compile Include="Collections\ReadOnlyDictionary.cs" />

     <Compile Include="Collections\RepeatedField.cs" />

     <Compile Include="DescriptorProtos\DescriptorProtoFile.cs" />

-    <Compile Include="DescriptorProtos\IDescriptorProto.cs" />

     <Compile Include="DescriptorProtos\PartialClasses.cs" />

     <Compile Include="Descriptors\DescriptorBase.cs" />

     <Compile Include="Descriptors\DescriptorPool.cs" />

@@ -74,11 +73,11 @@
     <Compile Include="Descriptors\FileDescriptor.cs" />

     <Compile Include="Descriptors\OneofDescriptor.cs" />

     <Compile Include="Descriptors\IDescriptor.cs" />

-    <Compile Include="Descriptors\IndexedDescriptorBase.cs" />

     <Compile Include="Descriptors\MessageDescriptor.cs" />

     <Compile Include="Descriptors\MethodDescriptor.cs" />

     <Compile Include="Descriptors\PackageDescriptor.cs" />

     <Compile Include="Descriptors\ServiceDescriptor.cs" />

+    <Compile Include="FieldAccess\MapFieldAccessor.cs" />

     <Compile Include="FieldCodec.cs" />

     <Compile Include="FrameworkPortability.cs" />

     <Compile Include="Freezable.cs" />

diff --git a/examples/addressbook.proto b/examples/addressbook.proto
index 9ab4542..5da5fa3 100644
--- a/examples/addressbook.proto
+++ b/examples/addressbook.proto
@@ -1,6 +1,6 @@
 // See README.txt for information and build instructions.
 
-syntax = "proto2";
+syntax = "proto3";
 
 package tutorial;
 
@@ -9,9 +9,9 @@
 option csharp_namespace = "Google.Protobuf.Examples.AddressBook";
 
 message Person {
-  required string name = 1;
-  required int32 id = 2;        // Unique ID number for this person.
-  optional string email = 3;
+  string name = 1;
+  int32 id = 2;        // Unique ID number for this person.
+  string email = 3;
 
   enum PhoneType {
     MOBILE = 0;
@@ -20,8 +20,8 @@
   }
 
   message PhoneNumber {
-    required string number = 1;
-    optional PhoneType type = 2 [default = HOME];
+    string number = 1;
+    PhoneType type = 2;
   }
 
   repeated PhoneNumber phone = 4;
diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc
index bfb39a6..ae7336c 100644
--- a/src/google/protobuf/compiler/csharp/csharp_field_base.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc
@@ -65,6 +65,7 @@
     tag_bytes += ", " + SimpleItoa(tag_array[i]);
   }
 
+  (*variables)["access_level"] = class_access_level();
   (*variables)["tag"] = SimpleItoa(tag);
   (*variables)["tag_size"] = SimpleItoa(tag_size);
   (*variables)["tag_bytes"] = tag_bytes;
diff --git a/src/google/protobuf/compiler/csharp/csharp_generator.cc b/src/google/protobuf/compiler/csharp/csharp_generator.cc
index 2a416fa..f06d79d 100644
--- a/src/google/protobuf/compiler/csharp/csharp_generator.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_generator.cc
@@ -68,6 +68,12 @@
   vector<pair<string, string> > options;
   ParseGeneratorParameter(parameter, &options);
 
+  // We only support proto3 - but we make an exception for descriptor.proto.
+  if (file->syntax() != FileDescriptor::SYNTAX_PROTO3 && !IsDescriptorProto(file)) {
+    *error = "C# code generation only supports proto3 syntax";
+    return false;
+  }
+
   std::string file_extension = ".cs";
   for (int i = 0; i < options.size(); i++) {
     if (options[i].first == "file_extension") {
diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.h b/src/google/protobuf/compiler/csharp/csharp_helpers.h
index a8c1fa1..d9576fb 100644
--- a/src/google/protobuf/compiler/csharp/csharp_helpers.h
+++ b/src/google/protobuf/compiler/csharp/csharp_helpers.h
@@ -101,6 +101,15 @@
 
 FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
 
+// Determines whether we're generating code for the proto representation of descriptors etc,
+// for use in the runtime. This is the only type which is allowed to use proto2 syntax,
+// and it generates internal classes.
+inline bool IsDescriptorProto(const FileDescriptor* descriptor) {
+  // TODO: Do this better! (Currently this depends on a hack in generate_protos.sh to rename
+  // the file...)
+  return descriptor->name() == "google/protobuf/descriptor_proto_file.proto";
+}
+
 }  // namespace csharp
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/csharp/csharp_map_field.cc b/src/google/protobuf/compiler/csharp/csharp_map_field.cc
index b8f1592..cb7ce5f 100644
--- a/src/google/protobuf/compiler/csharp/csharp_map_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_map_field.cc
@@ -78,7 +78,7 @@
   AddDeprecatedFlag(printer);
   printer->Print(
     variables_,
-    "public pbc::MapField<$key_type_name$, $value_type_name$> $property_name$ {\n"
+    "$access_level$ pbc::MapField<$key_type_name$, $value_type_name$> $property_name$ {\n"
     "  get { return $name$_; }\n"
     "}\n");
 }
diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc
index 9e2fe9b..13544b2 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_message.cc
@@ -116,8 +116,7 @@
 
   // The descriptor for this type.
   printer->Print(
-      "internal static pbd::MessageDescriptor internal__$identifier$__Descriptor;\n"
-      "internal static pb::FieldAccess.FieldAccessorTable<$full_class_name$> internal__$identifier$__FieldAccessorTable;\n",
+      "internal static pb::FieldAccess.FieldAccessorTable internal__$identifier$__FieldAccessorTable;\n",
       "identifier", GetUniqueFileScopeIdentifier(descriptor_),
       "full_class_name", full_class_name());
 
@@ -130,24 +129,23 @@
 void MessageGenerator::GenerateStaticVariableInitializers(io::Printer* printer) {
   map<string, string> vars;
   vars["identifier"] = GetUniqueFileScopeIdentifier(descriptor_);
-  vars["index"] = SimpleItoa(descriptor_->index());
   vars["full_class_name"] = full_class_name();
-  if (descriptor_->containing_type() != NULL) {
-    vars["parent"] = GetUniqueFileScopeIdentifier(
-	descriptor_->containing_type());
-  }
-  printer->Print(vars, "internal__$identifier$__Descriptor = ");
 
-  if (!descriptor_->containing_type()) {
-    printer->Print(vars, "Descriptor.MessageTypes[$index$];\n");
-  } else {
-    printer->Print(vars, "internal__$parent$__Descriptor.NestedTypes[$index$];\n");
+  // 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 pb::FieldAccess.FieldAccessorTable<$full_class_name$>(internal__$identifier$__Descriptor,\n");
+    "    new pb::FieldAccess.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$\", ",
@@ -201,23 +199,35 @@
     "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()) {
+    vars["descriptor_accessor"] = GetFullUmbrellaClassName(descriptor_->file())
+        + ".Descriptor.MessageTypes[" + SimpleItoa(descriptor_->index()) + "]";
+  } else {
+    vars["descriptor_accessor"] = GetClassName(descriptor_->containing_type())
+        + ".Descriptor.NestedTypes[" + SimpleItoa(descriptor_->index()) + "]";
+  }
+
   printer->Print(
     vars,
     "public static pbd::MessageDescriptor Descriptor {\n"
-    "  get { return $umbrella_class_name$.internal__$identifier$__Descriptor; }\n"
+    "  get { return $descriptor_accessor$; }\n"
     "}\n"
     "\n"
-    "public pb::FieldAccess.FieldAccessorTable<$class_name$> Fields {\n"
+    "public pb::FieldAccess.FieldAccessorTable Fields {\n"
     "  get { return $umbrella_class_name$.internal__$identifier$__FieldAccessorTable; }\n"
     "}\n"
     "\n"
     "private bool _frozen = false;\n"
     "public bool IsFrozen { get { return _frozen; } }\n\n");
 
-  // Parameterless constructor
+  // Parameterless constructor and partial OnConstruction method.
   printer->Print(
     vars,
-    "public $class_name$() { }\n\n");
+    "public $class_name$() {\n"
+    "  OnConstruction();\n"
+    "}\n\n"
+    "partial void OnConstruction();\n\n");
 
   GenerateCloningCode(printer);
   GenerateFreezingCode(printer);
@@ -304,7 +314,7 @@
   vars["class_name"] = class_name();
     printer->Print(
     vars,
-    "public $class_name$($class_name$ other) {\n");
+    "public $class_name$($class_name$ other) : this() {\n");
   printer->Indent();
   // Clone non-oneof fields first
   for (int i = 0; i < descriptor_->field_count(); i++) {
diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_message_field.cc
index d8c8227..d2c3a88 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_message_field.cc
@@ -64,7 +64,7 @@
   AddDeprecatedFlag(printer);
   printer->Print(
     variables_,
-    "public $type_name$ $property_name$ {\n"
+    "$access_level$ $type_name$ $property_name$ {\n"
     "  get { return $name$_; }\n"
     "  set {\n"
     "    pb::Freezable.CheckMutable(this);\n"
@@ -158,7 +158,7 @@
   AddDeprecatedFlag(printer);
   printer->Print(
     variables_,
-    "public $type_name$ $property_name$ {\n"
+    "$access_level$ $type_name$ $property_name$ {\n"
     "  get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : null; }\n"
     "  set {\n"
     "    pb::Freezable.CheckMutable(this);\n"
diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
index c40cba1..4454ef0 100644
--- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
@@ -71,7 +71,7 @@
   AddDeprecatedFlag(printer);
   printer->Print(
     variables_,
-    "public $type_name$ $property_name$ {\n"
+    "$access_level$ $type_name$ $property_name$ {\n"
     "  get { return $name$_; }\n"
     "  set {\n"
     "    pb::Freezable.CheckMutable(this);\n");
@@ -174,7 +174,7 @@
   AddDeprecatedFlag(printer);
   printer->Print(
     variables_,
-    "public $type_name$ $property_name$ {\n"
+    "$access_level$ $type_name$ $property_name$ {\n"
     "  get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : $default_value$; }\n"
     "  set {\n"
     "    pb::Freezable.CheckMutable(this);\n");
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
index 4445c28..d5fc6d9 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
@@ -65,7 +65,7 @@
   AddDeprecatedFlag(printer);
   printer->Print(
     variables_,
-    "public pbc::RepeatedField<$type_name$> $property_name$ {\n"
+    "$access_level$ pbc::RepeatedField<$type_name$> $property_name$ {\n"
     "  get { return $name$_; }\n"
     "}\n");
 }
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
index c74e5d0..6d4e698 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
@@ -65,7 +65,7 @@
   AddDeprecatedFlag(printer);
   printer->Print(
     variables_,
-    "public pbc::RepeatedField<$type_name$> $property_name$ {\n"
+    "$access_level$ pbc::RepeatedField<$type_name$> $property_name$ {\n"
     "  get { return $name$_; }\n"
     "}\n");
 }
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
index a3014da..5b5d9b3 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
@@ -65,7 +65,7 @@
   AddDeprecatedFlag(printer);
   printer->Print(
     variables_,
-    "public pbc::RepeatedField<$type_name$> $property_name$ {\n"
+    "$access_level$ pbc::RepeatedField<$type_name$> $property_name$ {\n"
     "  get { return $name$_; }\n"
     "}\n");
 }
diff --git a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc
index c666c82..735d164 100644
--- a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc
@@ -57,7 +57,7 @@
 }
 
 std::string SourceGeneratorBase::class_access_level() {
-  return "public";  // public_classes is always on.
+  return IsDescriptorProto(descriptor_) ? "internal" : "public";  // public_classes is always on.
 }
 
 }  // namespace csharp
diff --git a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc
index 03a3b8d..8fbd3e9 100644
--- a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc
@@ -176,22 +176,11 @@
   printer->Print("\"$base64$\"));\n", "base64", base64);
   printer->Outdent();
   printer->Outdent();
-  printer->Print(
-    "pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {\n");
-  printer->Indent();
-  printer->Print("descriptor = root;\n");
-  for (int i = 0; i < file_->message_type_count(); i++) {
-    MessageGenerator messageGenerator(file_->message_type(i));
-    messageGenerator.GenerateStaticVariableInitializers(printer);
-  }
-
-  printer->Outdent();
-  printer->Print("};\n");
 
   // -----------------------------------------------------------------
-  // Invoke internalBuildGeneratedFileFrom() to build the file.
+  // Invoke InternalBuildGeneratedFileFrom() to build the file.
   printer->Print(
-      "pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,\n");
+      "descriptor = pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,\n");
   printer->Print("    new pbd::FileDescriptor[] {\n");
   for (int i = 0; i < file_->dependency_count(); i++) {
     printer->Print(
@@ -199,7 +188,12 @@
       "full_umbrella_class_name",
       GetFullUmbrellaClassName(file_->dependency(i)));
   }
-  printer->Print("    }, assigner);\n");
+  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->Outdent();
   printer->Print("}\n");
   printer->Print("#endregion\n\n");