Adding conditional compiler symbol to support .NET 3.5 (#1713)

* Adding condition compiler symbol to support .NET 3.5
diff --git a/csharp/src/Google.Protobuf.Test/Compatibility/TypeExtensionsTest.cs b/csharp/src/Google.Protobuf.Test/Compatibility/TypeExtensionsTest.cs
index f0c8d3b..359c72c 100644
--- a/csharp/src/Google.Protobuf.Test/Compatibility/TypeExtensionsTest.cs
+++ b/csharp/src/Google.Protobuf.Test/Compatibility/TypeExtensionsTest.cs
@@ -67,7 +67,7 @@
         {
             Assert.AreEqual(expected, TypeExtensions.IsValueType(type));
         }
-
+#if !DOTNET35
         [Test]
         [TestCase(typeof(object), typeof(string), true)]
         [TestCase(typeof(object), typeof(int), true)]
@@ -129,5 +129,6 @@
         {
             Assert.Throws<AmbiguousMatchException>(() => TypeExtensions.GetMethod(type, name));
         }
+#endif
     }
 }
diff --git a/csharp/src/Google.Protobuf/Compatibility/PropertyInfoExtensions.cs b/csharp/src/Google.Protobuf/Compatibility/PropertyInfoExtensions.cs
index 8a6fefa..e3914dd 100644
--- a/csharp/src/Google.Protobuf/Compatibility/PropertyInfoExtensions.cs
+++ b/csharp/src/Google.Protobuf/Compatibility/PropertyInfoExtensions.cs
@@ -47,7 +47,11 @@
         /// </summary>
         internal static MethodInfo GetGetMethod(this PropertyInfo target)
         {
+#if DOTNET35
+            var method = target.GetGetMethod();
+#else
             var method = target.GetMethod;
+#endif
             return method != null && method.IsPublic ? method : null;
         }
 
@@ -57,7 +61,11 @@
         /// </summary>
         internal static MethodInfo GetSetMethod(this PropertyInfo target)
         {
+#if DOTNET35
+            var method = target.GetSetMethod();
+#else
             var method = target.SetMethod;
+#endif
             return method != null && method.IsPublic ? method : null;
         }
     }
diff --git a/csharp/src/Google.Protobuf/Compatibility/TypeExtensions.cs b/csharp/src/Google.Protobuf/Compatibility/TypeExtensions.cs
index 762a29e..fe9cda8 100644
--- a/csharp/src/Google.Protobuf/Compatibility/TypeExtensions.cs
+++ b/csharp/src/Google.Protobuf/Compatibility/TypeExtensions.cs
@@ -49,6 +49,11 @@
         /// Returns true if the target type is a value type, including a nullable value type or an enum, or false
         /// if it's a reference type (class, delegate, interface - including System.ValueType and System.Enum).
         /// </summary>
+#if DOTNET35
+        internal static bool IsValueType(this Type target) {
+            return target.IsValueType;
+        }
+#else
         internal static bool IsValueType(this Type target)
         {
             return target.GetTypeInfo().IsValueType;
@@ -109,5 +114,6 @@
             }
             return null;
         }
+#endif
     }
 }
diff --git a/csharp/src/Google.Protobuf/JsonFormatter.cs b/csharp/src/Google.Protobuf/JsonFormatter.cs
index 2aa98cd..a894ffa 100644
--- a/csharp/src/Google.Protobuf/JsonFormatter.cs
+++ b/csharp/src/Google.Protobuf/JsonFormatter.cs
@@ -885,6 +885,16 @@
                 return originalName;
             }
 
+#if DOTNET35
+            // TODO: Consider adding functionality to TypeExtensions to avoid this difference.
+            private static Dictionary<object, string> GetNameMapping(System.Type enumType) =>
+                enumType.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static)
+                    .ToDictionary(f => f.GetValue(null),
+                                  f => (f.GetCustomAttributes(typeof(OriginalNameAttribute), false)
+                                        .FirstOrDefault() as OriginalNameAttribute)
+                                        // If the attribute hasn't been applied, fall back to the name of the field.
+                                        ?.Name ?? f.Name);
+#else
             private static Dictionary<object, string> GetNameMapping(System.Type enumType) =>
                 enumType.GetTypeInfo().DeclaredFields
                     .Where(f => f.IsStatic)
@@ -893,6 +903,7 @@
                                         .FirstOrDefault()
                                         // If the attribute hasn't been applied, fall back to the name of the field.
                                         ?.Name ?? f.Name);
+#endif
         }
     }
 }
diff --git a/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs
index f5a835e..7a1cb9d 100644
--- a/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs
@@ -34,6 +34,10 @@
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using System.Linq;
+#if DOTNET35
+// Needed for ReadOnlyDictionary, which does not exist in .NET 3.5
+using Google.Protobuf.Collections;
+#endif
 
 namespace Google.Protobuf.Reflection
 {
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/FieldMaskPartial.cs b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMaskPartial.cs
index 4bd62cf..f9cdb8a 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/FieldMaskPartial.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMaskPartial.cs
@@ -59,7 +59,12 @@
             if (firstInvalid == null)
             {
                 var writer = new StringWriter();
+#if DOTNET35
+                var query = paths.Select(JsonFormatter.ToCamelCase);
+                JsonFormatter.WriteString(writer, string.Join(",", query.ToArray()));
+#else
                 JsonFormatter.WriteString(writer, string.Join(",", paths.Select(JsonFormatter.ToCamelCase)));
+#endif
                 return writer.ToString();
             }
             else
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/TimeExtensions.cs b/csharp/src/Google.Protobuf/WellKnownTypes/TimeExtensions.cs
index dd485d3..8b63d63 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/TimeExtensions.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/TimeExtensions.cs
@@ -31,10 +31,6 @@
 #endregion
 
 using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace Google.Protobuf.WellKnownTypes
 {