Introduce a Parser property into MessageDescriptor, and populate it from generated types.
Generated code coming in next commit - in a subsequent PR I want to do a bit of renaming and redocumenting around this, in anticipation of DynamicMessage.
diff --git a/csharp/src/Google.Protobuf/JsonParser.cs b/csharp/src/Google.Protobuf/JsonParser.cs
index 9e1c83c..b4a35d7 100644
--- a/csharp/src/Google.Protobuf/JsonParser.cs
+++ b/csharp/src/Google.Protobuf/JsonParser.cs
@@ -555,14 +555,10 @@
 
         /// <summary>
         /// Creates a new instance of the message type for the given field.
-        /// This method is mostly extracted so we can replace it in one go when we work out
-        /// what we want to do instead of Activator.CreateInstance.
         /// </summary>
         private static IMessage NewMessageForField(FieldDescriptor field)
         {
-            // TODO: Create an instance in a better way ?
-            // (We could potentially add a Parser property to MessageDescriptor... see issue 806.)
-            return (IMessage) Activator.CreateInstance(field.MessageType.GeneratedType);
+            return field.MessageType.Parser.CreateTemplate();
         }
 
         private static T ParseNumericString<T>(string text, Func<string, NumberStyles, IFormatProvider, T> parser, bool floatingPoint)
diff --git a/csharp/src/Google.Protobuf/MessageParser.cs b/csharp/src/Google.Protobuf/MessageParser.cs
index 8f2717c..f911c9d 100644
--- a/csharp/src/Google.Protobuf/MessageParser.cs
+++ b/csharp/src/Google.Protobuf/MessageParser.cs
@@ -36,6 +36,109 @@
 namespace Google.Protobuf
 {
     /// <summary>
+    /// A general message parser, typically used by reflection-based code as all the methods
+    /// return simple <see cref="IMessage"/>.
+    /// </summary>
+    public class MessageParser
+    {
+        private Func<IMessage> factory;
+
+        internal MessageParser(Func<IMessage> factory)
+        {
+            this.factory = factory;
+        }
+
+        /// <summary>
+        /// Creates a template instance ready for population.
+        /// </summary>
+        /// <returns>An empty message.</returns>
+        internal IMessage CreateTemplate()
+        {
+            return factory();
+        }
+
+        /// <summary>
+        /// Parses a message from a byte array.
+        /// </summary>
+        /// <param name="data">The byte array containing the message. Must not be null.</param>
+        /// <returns>The newly parsed message.</returns>
+        public IMessage ParseFrom(byte[] data)
+        {
+            Preconditions.CheckNotNull(data, "data");
+            IMessage message = factory();
+            message.MergeFrom(data);
+            return message;
+        }
+
+        /// <summary>
+        /// Parses a message from the given byte string.
+        /// </summary>
+        /// <param name="data">The data to parse.</param>
+        /// <returns>The parsed message.</returns>
+        public IMessage ParseFrom(ByteString data)
+        {
+            Preconditions.CheckNotNull(data, "data");
+            IMessage message = factory();
+            message.MergeFrom(data);
+            return message;
+        }
+
+        /// <summary>
+        /// Parses a message from the given stream.
+        /// </summary>
+        /// <param name="input">The stream to parse.</param>
+        /// <returns>The parsed message.</returns>
+        public IMessage ParseFrom(Stream input)
+        {
+            IMessage message = factory();
+            message.MergeFrom(input);
+            return message;
+        }
+
+        /// <summary>
+        /// Parses a length-delimited message from the given stream.
+        /// </summary>
+        /// <remarks>
+        /// The stream is expected to contain a length and then the data. Only the amount of data
+        /// specified by the length will be consumed.
+        /// </remarks>
+        /// <param name="input">The stream to parse.</param>
+        /// <returns>The parsed message.</returns>
+        public IMessage ParseDelimitedFrom(Stream input)
+        {
+            IMessage message = factory();
+            message.MergeDelimitedFrom(input);
+            return message;
+        }
+
+        /// <summary>
+        /// Parses a message from the given coded input stream.
+        /// </summary>
+        /// <param name="input">The stream to parse.</param>
+        /// <returns>The parsed message.</returns>
+        public IMessage ParseFrom(CodedInputStream input)
+        {
+            IMessage message = factory();
+            message.MergeFrom(input);
+            return message;
+        }
+
+        /// <summary>
+        /// Parses a message from the given JSON.
+        /// </summary>
+        /// <param name="json">The JSON to parse.</param>
+        /// <returns>The parsed message.</returns>
+        /// <exception cref="InvalidJsonException">The JSON does not comply with RFC 7159</exception>
+        /// <exception cref="InvalidProtocolBufferException">The JSON does not represent a Protocol Buffers message correctly</exception>
+        public IMessage ParseJson(string json)
+        {
+            IMessage message = factory();
+            JsonParser.Default.Merge(message, json);
+            return message;
+        }
+    }
+
+    /// <summary>
     /// A parser for a specific message type.
     /// </summary>
     /// <remarks>
@@ -51,8 +154,10 @@
     /// </p>
     /// </remarks>
     /// <typeparam name="T">The type of message to be parsed.</typeparam>
-    public sealed class MessageParser<T> where T : IMessage<T>
+    public sealed class MessageParser<T> : MessageParser where T : IMessage<T>
     {
+        // Implementation note: all the methods here *could* just delegate up to the base class and cast the result.
+        // The 
         private readonly Func<T> factory; 
 
         /// <summary>
@@ -63,7 +168,7 @@
         /// to require a parameterless constructor: delegates are significantly faster to execute.
         /// </remarks>
         /// <param name="factory">Function to invoke when a new, empty message is required.</param>
-        public MessageParser(Func<T> factory)
+        public MessageParser(Func<T> factory) : base(() => factory())
         {
             this.factory = factory;
         }
@@ -72,7 +177,7 @@
         /// Creates a template instance ready for population.
         /// </summary>
         /// <returns>An empty message.</returns>
-        internal T CreateTemplate()
+        internal new T CreateTemplate()
         {
             return factory();
         }
@@ -82,7 +187,7 @@
         /// </summary>
         /// <param name="data">The byte array containing the message. Must not be null.</param>
         /// <returns>The newly parsed message.</returns>
-        public T ParseFrom(byte[] data)
+        public new T ParseFrom(byte[] data)
         {
             Preconditions.CheckNotNull(data, "data");
             T message = factory();
@@ -95,7 +200,7 @@
         /// </summary>
         /// <param name="data">The data to parse.</param>
         /// <returns>The parsed message.</returns>
-        public T ParseFrom(ByteString data)
+        public new T ParseFrom(ByteString data)
         {
             Preconditions.CheckNotNull(data, "data");
             T message = factory();
@@ -108,7 +213,7 @@
         /// </summary>
         /// <param name="input">The stream to parse.</param>
         /// <returns>The parsed message.</returns>
-        public T ParseFrom(Stream input)
+        public new T ParseFrom(Stream input)
         {
             T message = factory();
             message.MergeFrom(input);
@@ -124,7 +229,7 @@
         /// </remarks>
         /// <param name="input">The stream to parse.</param>
         /// <returns>The parsed message.</returns>
-        public T ParseDelimitedFrom(Stream input)
+        public new T ParseDelimitedFrom(Stream input)
         {
             T message = factory();
             message.MergeDelimitedFrom(input);
@@ -136,7 +241,7 @@
         /// </summary>
         /// <param name="input">The stream to parse.</param>
         /// <returns>The parsed message.</returns>
-        public T ParseFrom(CodedInputStream input)
+        public new T ParseFrom(CodedInputStream input)
         {
             T message = factory();
             message.MergeFrom(input);
@@ -150,7 +255,7 @@
         /// <returns>The parsed message.</returns>
         /// <exception cref="InvalidJsonException">The JSON does not comply with RFC 7159</exception>
         /// <exception cref="InvalidProtocolBufferException">The JSON does not represent a Protocol Buffers message correctly</exception>
-        public T ParseJson(string json)
+        public new T ParseJson(string json)
         {
             T message = factory();
             JsonParser.Default.Merge(message, json);
diff --git a/csharp/src/Google.Protobuf/Reflection/GeneratedCodeInfo.cs b/csharp/src/Google.Protobuf/Reflection/GeneratedCodeInfo.cs
index 8c52cd1..ff4ad0a 100644
--- a/csharp/src/Google.Protobuf/Reflection/GeneratedCodeInfo.cs
+++ b/csharp/src/Google.Protobuf/Reflection/GeneratedCodeInfo.cs
@@ -18,6 +18,11 @@
         public Type ClrType { get; private set; }
 
         /// <summary>
+        /// Irrelevant for file descriptors; the parser for message descriptors.
+        /// </summary>
+        public MessageParser Parser { get; private set; }
+
+        /// <summary>
         /// Irrelevant for file descriptors; the CLR property names (in message descriptor field order)
         /// for fields in the message for message descriptors.
         /// </summary>
@@ -46,11 +51,12 @@
         /// Each array parameter may be null, to indicate a lack of values.
         /// The parameter order is designed to make it feasible to format the generated code readably.
         /// </summary>
-        public GeneratedCodeInfo(Type clrType, string[] propertyNames, string[] oneofNames, Type[] nestedEnums, GeneratedCodeInfo[] nestedTypes)
+        public GeneratedCodeInfo(Type clrType, MessageParser parser, string[] propertyNames, string[] oneofNames, Type[] nestedEnums, GeneratedCodeInfo[] nestedTypes)
         {
             NestedTypes = nestedTypes ?? EmptyCodeInfo;
             NestedEnums = nestedEnums ?? ReflectionUtil.EmptyTypes;
             ClrType = clrType;
+            Parser = parser;
             PropertyNames = propertyNames ?? EmptyNames;
             OneofNames = oneofNames ?? EmptyNames;
         }
@@ -59,7 +65,7 @@
         /// Creates a GeneratedCodeInfo for a file descriptor, with only types and enums.
         /// </summary>
         public GeneratedCodeInfo(Type[] nestedEnums, GeneratedCodeInfo[] nestedTypes)
-            : this(null, null, null, nestedEnums, nestedTypes)
+            : this(null, null, null, null, nestedEnums, nestedTypes)
         {
         }
     }
diff --git a/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs
index e599998..65040e4 100644
--- a/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs
@@ -67,11 +67,13 @@
         private readonly IList<OneofDescriptor> oneofs;
         // CLR representation of the type described by this descriptor, if any.
         private readonly Type generatedType;
+        private readonly MessageParser parser;
         
         internal MessageDescriptor(DescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int typeIndex, GeneratedCodeInfo generatedCodeInfo)
             : base(file, file.ComputeFullName(parent, proto.Name), typeIndex)
         {
             this.proto = proto;
+            parser = generatedCodeInfo == null ? null : generatedCodeInfo.Parser;
             generatedType = generatedCodeInfo == null ? null : generatedCodeInfo.ClrType;
 
             containingType = parent;
@@ -123,6 +125,15 @@
         public Type GeneratedType { get { return generatedType; } }
 
         /// <summary>
+        /// A parser for this message type.
+        /// </summary>
+        /// <remarks>
+        /// As <see cref="MessageDescriptor"/> is not generic, this cannot be statically
+        /// typed to the relevant type, but if <see cref="GeneratedType"/> returns a non-null value, the parser returned
+        /// </remarks>
+        public MessageParser Parser { get { return parser; } }
+
+        /// <summary>
         /// Returns whether this message is one of the "well known types" which may have runtime/protoc support.
         /// </summary>
         internal bool IsWellKnownType
diff --git a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc
index 8059fd2..812c6fc 100644
--- a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc
@@ -232,7 +232,7 @@
     return;
   }
   // Generated message type
-  printer->Print("new pbr::GeneratedCodeInfo(typeof($type_name$), ", "type_name", GetClassName(descriptor));
+  printer->Print("new pbr::GeneratedCodeInfo(typeof($type_name$), $type_name$.Parser, ", "type_name", GetClassName(descriptor));
   
   // Fields
   if (descriptor->field_count() > 0) {