Jon Skeet 13 anni fa
parent
commit
57e5746a39

+ 6 - 1
protos/extest/unittest_issues.proto

@@ -129,4 +129,9 @@ message DeprecatedFieldsMessage {
 
     optional DeprecatedEnum EnumValue = 5 [deprecated = true];
     repeated DeprecatedEnum EnumArray = 6 [deprecated = true];
-}
+}
+
+// Issue 45: http://code.google.com/p/protobuf-csharp-port/issues/detail?id=45
+message ItemField {
+  optional int32 item = 1;
+}

+ 59 - 0
src/ProtocolBuffers.Test/IssuesTest.cs

@@ -0,0 +1,59 @@
+#region Copyright notice and license
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using Google.ProtocolBuffers.Descriptors;
+using NUnit.Framework;
+using UnitTest.Issues.TestProtos;
+
+namespace Google.ProtocolBuffers
+{
+    /// <summary>
+    /// Tests for issues which aren't easily compartmentalized into other unit tests.
+    /// </summary>
+    [TestFixture]
+    public class IssuesTest
+    {
+        // Issue 45
+        [Test]
+        public void FieldCalledItem()
+        {
+            ItemField message = new ItemField.Builder { Item = 3 }.Build();
+            FieldDescriptor field = ItemField.Descriptor.FindFieldByName("item");
+            Assert.IsNotNull(field);
+            Assert.AreEqual(3, message[field]);
+        }
+    }
+}

+ 1 - 0
src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj

@@ -94,6 +94,7 @@
     <Compile Include="ExtendableMessageTest.cs" />
     <Compile Include="GeneratedBuilderTest.cs" />
     <Compile Include="GeneratedMessageTest.cs" />
+    <Compile Include="IssuesTest.cs" />
     <Compile Include="MessageStreamIteratorTest.cs" />
     <Compile Include="MessageStreamWriterTest.cs" />
     <Compile Include="MessageTest.cs" />

+ 285 - 5
src/ProtocolBuffers.Test/TestProtos/UnitTestExtrasIssuesProtoFile.cs

@@ -36,6 +36,8 @@ namespace UnitTest.Issues.TestProtos {
     internal static pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.DeprecatedChild, global::UnitTest.Issues.TestProtos.DeprecatedChild.Builder> internal__static_unittest_issues_DeprecatedChild__FieldAccessorTable;
     internal static pbd::MessageDescriptor internal__static_unittest_issues_DeprecatedFieldsMessage__Descriptor;
     internal static pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage, global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage.Builder> internal__static_unittest_issues_DeprecatedFieldsMessage__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_unittest_issues_ItemField__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.ItemField, global::UnitTest.Issues.TestProtos.ItemField.Builder> internal__static_unittest_issues_ItemField__FieldAccessorTable;
     #endregion
     #region Descriptor
     public static pbd::FileDescriptor Descriptor {
@@ -63,11 +65,11 @@ namespace UnitTest.Issues.TestProtos {
           "eRgEIAMoCzIgLnVuaXR0ZXN0X2lzc3Vlcy5EZXByZWNhdGVkQ2hpbGRCAhgB" + 
           "EjYKCUVudW1WYWx1ZRgFIAEoDjIfLnVuaXR0ZXN0X2lzc3Vlcy5EZXByZWNh" + 
           "dGVkRW51bUICGAESNgoJRW51bUFycmF5GAYgAygOMh8udW5pdHRlc3RfaXNz" + 
-          "dWVzLkRlcHJlY2F0ZWRFbnVtQgIYASpHCgxOZWdhdGl2ZUVudW0SFgoJRml2" + 
-          "ZUJlbG93EPv//////////wESFQoITWludXNPbmUQ////////////ARIICgRa" + 
-          "ZXJvEAAqGQoORGVwcmVjYXRlZEVudW0SBwoDb25lEAFCQEgBwj47ChpVbml0" + 
-          "VGVzdC5Jc3N1ZXMuVGVzdFByb3RvcxIdVW5pdFRlc3RFeHRyYXNJc3N1ZXNQ" + 
-          "cm90b0ZpbGU=");
+          "dWVzLkRlcHJlY2F0ZWRFbnVtQgIYASIZCglJdGVtRmllbGQSDAoEaXRlbRgB" + 
+          "IAEoBSpHCgxOZWdhdGl2ZUVudW0SFgoJRml2ZUJlbG93EPv//////////wES" + 
+          "FQoITWludXNPbmUQ////////////ARIICgRaZXJvEAAqGQoORGVwcmVjYXRl" + 
+          "ZEVudW0SBwoDb25lEAFCQEgBwj47ChpVbml0VGVzdC5Jc3N1ZXMuVGVzdFBy" + 
+          "b3RvcxIdVW5pdFRlc3RFeHRyYXNJc3N1ZXNQcm90b0ZpbGU=");
       pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {
         descriptor = root;
         internal__static_unittest_issues_A__Descriptor = Descriptor.MessageTypes[0];
@@ -106,6 +108,10 @@ namespace UnitTest.Issues.TestProtos {
         internal__static_unittest_issues_DeprecatedFieldsMessage__FieldAccessorTable = 
             new pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage, global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage.Builder>(internal__static_unittest_issues_DeprecatedFieldsMessage__Descriptor,
                 new string[] { "PrimitiveValue", "PrimitiveArray", "MessageValue", "MessageArray", "EnumValue", "EnumArray", });
+        internal__static_unittest_issues_ItemField__Descriptor = Descriptor.MessageTypes[9];
+        internal__static_unittest_issues_ItemField__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.ItemField, global::UnitTest.Issues.TestProtos.ItemField.Builder>(internal__static_unittest_issues_ItemField__Descriptor,
+                new string[] { "Item", });
         pb::ExtensionRegistry registry = pb::ExtensionRegistry.CreateInstance();
         RegisterAllExtensions(registry);
         global::Google.ProtocolBuffers.DescriptorProtos.CSharpOptions.RegisterAllExtensions(registry);
@@ -3151,6 +3157,280 @@ namespace UnitTest.Issues.TestProtos {
     }
   }
   
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+  [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.4.1.473")]
+  public sealed partial class ItemField : pb::GeneratedMessage<ItemField, ItemField.Builder> {
+    private ItemField() { }
+    private static readonly ItemField defaultInstance = new ItemField().MakeReadOnly();
+    private static readonly string[] _itemFieldFieldNames = new string[] { "item" };
+    private static readonly uint[] _itemFieldFieldTags = new uint[] { 8 };
+    public static ItemField DefaultInstance {
+      get { return defaultInstance; }
+    }
+    
+    public override ItemField DefaultInstanceForType {
+      get { return DefaultInstance; }
+    }
+    
+    protected override ItemField ThisMessage {
+      get { return this; }
+    }
+    
+    public static pbd::MessageDescriptor Descriptor {
+      get { return global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.internal__static_unittest_issues_ItemField__Descriptor; }
+    }
+    
+    protected override pb::FieldAccess.FieldAccessorTable<ItemField, ItemField.Builder> InternalFieldAccessors {
+      get { return global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.internal__static_unittest_issues_ItemField__FieldAccessorTable; }
+    }
+    
+    public const int ItemFieldNumber = 1;
+    private bool hasItem;
+    private int item_;
+    public bool HasItem {
+      get { return hasItem; }
+    }
+    public int Item {
+      get { return item_; }
+    }
+    
+    public override bool IsInitialized {
+      get {
+        return true;
+      }
+    }
+    
+    public override void WriteTo(pb::ICodedOutputStream output) {
+      int size = SerializedSize;
+      string[] field_names = _itemFieldFieldNames;
+      if (hasItem) {
+        output.WriteInt32(1, field_names[0], Item);
+      }
+      UnknownFields.WriteTo(output);
+    }
+    
+    private int memoizedSerializedSize = -1;
+    public override int SerializedSize {
+      get {
+        int size = memoizedSerializedSize;
+        if (size != -1) return size;
+        
+        size = 0;
+        if (hasItem) {
+          size += pb::CodedOutputStream.ComputeInt32Size(1, Item);
+        }
+        size += UnknownFields.SerializedSize;
+        memoizedSerializedSize = size;
+        return size;
+      }
+    }
+    
+    public static ItemField ParseFrom(pb::ByteString data) {
+      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+    }
+    public static ItemField ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
+      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+    }
+    public static ItemField ParseFrom(byte[] data) {
+      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+    }
+    public static ItemField ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
+      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+    }
+    public static ItemField ParseFrom(global::System.IO.Stream input) {
+      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+    }
+    public static ItemField ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
+      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+    }
+    public static ItemField ParseDelimitedFrom(global::System.IO.Stream input) {
+      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
+    }
+    public static ItemField ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
+      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
+    }
+    public static ItemField ParseFrom(pb::ICodedInputStream input) {
+      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+    }
+    public static ItemField ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+    }
+    private ItemField MakeReadOnly() {
+      return this;
+    }
+    
+    public static Builder CreateBuilder() { return new Builder(); }
+    public override Builder ToBuilder() { return CreateBuilder(this); }
+    public override Builder CreateBuilderForType() { return new Builder(); }
+    public static Builder CreateBuilder(ItemField prototype) {
+      return new Builder(prototype);
+    }
+    
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.4.1.473")]
+    public sealed partial class Builder : pb::GeneratedBuilder<ItemField, Builder> {
+      protected override Builder ThisBuilder {
+        get { return this; }
+      }
+      public Builder() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+      }
+      internal Builder(ItemField cloneFrom) {
+        result = cloneFrom;
+        resultIsReadOnly = true;
+      }
+      
+      private bool resultIsReadOnly;
+      private ItemField result;
+      
+      private ItemField PrepareBuilder() {
+        if (resultIsReadOnly) {
+          ItemField original = result;
+          result = new ItemField();
+          resultIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
+      
+      protected override ItemField MessageBeingBuilt {
+        get { return PrepareBuilder(); }
+      }
+      
+      public override Builder Clear() {
+        result = DefaultInstance;
+        resultIsReadOnly = true;
+        return this;
+      }
+      
+      public override Builder Clone() {
+        if (resultIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
+      }
+      
+      public override pbd::MessageDescriptor DescriptorForType {
+        get { return global::UnitTest.Issues.TestProtos.ItemField.Descriptor; }
+      }
+      
+      public override ItemField DefaultInstanceForType {
+        get { return global::UnitTest.Issues.TestProtos.ItemField.DefaultInstance; }
+      }
+      
+      public override ItemField BuildPartial() {
+        if (resultIsReadOnly) {
+          return result;
+        }
+        resultIsReadOnly = true;
+        return result.MakeReadOnly();
+      }
+      
+      public override Builder MergeFrom(pb::IMessage other) {
+        if (other is ItemField) {
+          return MergeFrom((ItemField) other);
+        } else {
+          base.MergeFrom(other);
+          return this;
+        }
+      }
+      
+      public override Builder MergeFrom(ItemField other) {
+        if (other == global::UnitTest.Issues.TestProtos.ItemField.DefaultInstance) return this;
+        PrepareBuilder();
+        if (other.HasItem) {
+          Item = other.Item;
+        }
+        this.MergeUnknownFields(other.UnknownFields);
+        return this;
+      }
+      
+      public override Builder MergeFrom(pb::ICodedInputStream input) {
+        return MergeFrom(input, pb::ExtensionRegistry.Empty);
+      }
+      
+      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
+        pb::UnknownFieldSet.Builder unknownFields = null;
+        uint tag;
+        string field_name;
+        while (input.ReadTag(out tag, out field_name)) {
+          if(tag == 0 && field_name != null) {
+            int field_ordinal = global::System.Array.BinarySearch(_itemFieldFieldNames, field_name, global::System.StringComparer.Ordinal);
+            if(field_ordinal >= 0)
+              tag = _itemFieldFieldTags[field_ordinal];
+            else {
+              if (unknownFields == null) {
+                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+              }
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+              continue;
+            }
+          }
+          switch (tag) {
+            case 0: {
+              throw pb::InvalidProtocolBufferException.InvalidTag();
+            }
+            default: {
+              if (pb::WireFormat.IsEndGroupTag(tag)) {
+                if (unknownFields != null) {
+                  this.UnknownFields = unknownFields.Build();
+                }
+                return this;
+              }
+              if (unknownFields == null) {
+                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+              }
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+              break;
+            }
+            case 8: {
+              result.hasItem = input.ReadInt32(ref result.item_);
+              break;
+            }
+          }
+        }
+        
+        if (unknownFields != null) {
+          this.UnknownFields = unknownFields.Build();
+        }
+        return this;
+      }
+      
+      
+      public bool HasItem {
+        get { return result.hasItem; }
+      }
+      public int Item {
+        get { return result.Item; }
+        set { SetItem(value); }
+      }
+      public Builder SetItem(int value) {
+        PrepareBuilder();
+        result.hasItem = true;
+        result.item_ = value;
+        return this;
+      }
+      public Builder ClearItem() {
+        PrepareBuilder();
+        result.hasItem = false;
+        result.item_ = 0;
+        return this;
+      }
+    }
+    static ItemField() {
+      object.ReferenceEquals(global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.Descriptor, null);
+    }
+  }
+  
   #endregion
   
 }

+ 5 - 0
src/ProtocolBuffers/FieldAccess/ReflectionUtil.cs

@@ -44,6 +44,11 @@ namespace Google.ProtocolBuffers.FieldAccess
     /// </summary>
     internal static class ReflectionUtil
     {
+        /// <summary>
+        /// Empty Type[] used when calling GetProperty to force property instead of indexer fetching.
+        /// </summary>
+        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.

+ 9 - 9
src/ProtocolBuffers/FieldAccess/RepeatedPrimitiveAccessor.cs

@@ -66,14 +66,14 @@ namespace Google.ProtocolBuffers.FieldAccess
 
         internal RepeatedPrimitiveAccessor(string name)
         {
-            PropertyInfo messageProperty = typeof (TMessage).GetProperty(name + "List");
-            PropertyInfo builderProperty = typeof (TBuilder).GetProperty(name + "List");
-            PropertyInfo countProperty = typeof (TMessage).GetProperty(name + "Count");
-            MethodInfo clearMethod = typeof (TBuilder).GetMethod("Clear" + name, EmptyTypes);
-            getElementMethod = typeof (TMessage).GetMethod("Get" + name, new Type[] {typeof (int)});
+            PropertyInfo messageProperty = typeof(TMessage).GetProperty(name + "List", ReflectionUtil.EmptyTypes);
+            PropertyInfo builderProperty = typeof(TBuilder).GetProperty(name + "List", ReflectionUtil.EmptyTypes);
+            PropertyInfo countProperty = typeof(TMessage).GetProperty(name + "Count", ReflectionUtil.EmptyTypes);
+            MethodInfo clearMethod = typeof(TBuilder).GetMethod("Clear" + name, EmptyTypes);
+            getElementMethod = typeof(TMessage).GetMethod("Get" + name, new Type[] {typeof(int)});
             clrType = getElementMethod.ReturnType;
-            MethodInfo addMethod = typeof (TBuilder).GetMethod("Add" + name, new Type[] {ClrType});
-            setElementMethod = typeof (TBuilder).GetMethod("Set" + name, new Type[] {typeof (int), ClrType});
+            MethodInfo addMethod = typeof(TBuilder).GetMethod("Add" + name, new Type[] {ClrType});
+            setElementMethod = typeof(TBuilder).GetMethod("Set" + name, new Type[] {typeof(int), ClrType});
             if (messageProperty == null
                 || builderProperty == null
                 || countProperty == null
@@ -85,9 +85,9 @@ namespace Google.ProtocolBuffers.FieldAccess
                 throw new ArgumentException("Not all required properties/methods available");
             }
             clearDelegate =
-                (Func<TBuilder, IBuilder>) Delegate.CreateDelegate(typeof (Func<TBuilder, IBuilder>), null, clearMethod);
+                (Func<TBuilder, IBuilder>) Delegate.CreateDelegate(typeof(Func<TBuilder, IBuilder>), null, clearMethod);
             countDelegate = (Func<TMessage, int>) Delegate.CreateDelegate
-                                                      (typeof (Func<TMessage, int>), null, countProperty.GetGetMethod());
+                                                      (typeof(Func<TMessage, int>), null, countProperty.GetGetMethod());
             getValueDelegate = ReflectionUtil.CreateUpcastDelegate<TMessage>(messageProperty.GetGetMethod());
             addValueDelegate = ReflectionUtil.CreateDowncastDelegateIgnoringReturn<TBuilder>(addMethod);
             getRepeatedWrapperDelegate = ReflectionUtil.CreateUpcastDelegate<TBuilder>(builderProperty.GetGetMethod());

+ 1 - 1
src/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs

@@ -50,7 +50,7 @@ namespace Google.ProtocolBuffers.FieldAccess
 
         internal SingleMessageAccessor(string name) : base(name)
         {
-            MethodInfo createBuilderMethod = ClrType.GetMethod("CreateBuilder", EmptyTypes);
+            MethodInfo createBuilderMethod = ClrType.GetMethod("CreateBuilder", ReflectionUtil.EmptyTypes);
             if (createBuilderMethod == null)
             {
                 throw new ArgumentException("No public static CreateBuilder method declared in " + ClrType.Name);

+ 7 - 9
src/ProtocolBuffers/FieldAccess/SinglePrimitiveAccessor.cs

@@ -47,8 +47,6 @@ namespace Google.ProtocolBuffers.FieldAccess
         private readonly Func<TMessage, bool> hasDelegate;
         private readonly Func<TBuilder, IBuilder> clearDelegate;
 
-        internal static readonly Type[] EmptyTypes = new Type[0];
-
         /// <summary>
         /// The CLR type of the field (int, the enum type, ByteString, the message etc).
         /// As declared by the property.
@@ -60,14 +58,14 @@ namespace Google.ProtocolBuffers.FieldAccess
 
         internal SinglePrimitiveAccessor(string name)
         {
-            PropertyInfo messageProperty = typeof (TMessage).GetProperty(name);
-            PropertyInfo builderProperty = typeof (TBuilder).GetProperty(name);
+            PropertyInfo messageProperty = typeof(TMessage).GetProperty(name, ReflectionUtil.EmptyTypes);
+            PropertyInfo builderProperty = typeof(TBuilder).GetProperty(name, ReflectionUtil.EmptyTypes);
             if (builderProperty == null)
             {
-                builderProperty = typeof (TBuilder).GetProperty(name);
+                builderProperty = typeof(TBuilder).GetProperty(name, ReflectionUtil.EmptyTypes);
             }
-            PropertyInfo hasProperty = typeof (TMessage).GetProperty("Has" + name);
-            MethodInfo clearMethod = typeof (TBuilder).GetMethod("Clear" + name, EmptyTypes);
+            PropertyInfo hasProperty = typeof(TMessage).GetProperty("Has" + name, ReflectionUtil.EmptyTypes);
+            MethodInfo clearMethod = typeof(TBuilder).GetMethod("Clear" + name, ReflectionUtil.EmptyTypes);
             if (messageProperty == null || builderProperty == null || hasProperty == null || clearMethod == null)
             {
                 throw new ArgumentException("Not all required properties/methods available");
@@ -75,9 +73,9 @@ namespace Google.ProtocolBuffers.FieldAccess
             clrType = messageProperty.PropertyType;
             hasDelegate =
                 (Func<TMessage, bool>)
-                Delegate.CreateDelegate(typeof (Func<TMessage, bool>), null, hasProperty.GetGetMethod());
+                Delegate.CreateDelegate(typeof(Func<TMessage, bool>), null, hasProperty.GetGetMethod());
             clearDelegate =
-                (Func<TBuilder, IBuilder>) Delegate.CreateDelegate(typeof (Func<TBuilder, IBuilder>), null, clearMethod);
+                (Func<TBuilder, IBuilder>) Delegate.CreateDelegate(typeof(Func<TBuilder, IBuilder>), null, clearMethod);
             getValueDelegate = ReflectionUtil.CreateUpcastDelegate<TMessage>(messageProperty.GetGetMethod());
             setValueDelegate = ReflectionUtil.CreateDowncastDelegate<TBuilder>(builderProperty.GetSetMethod());
         }