aboutsummaryrefslogtreecommitdiff
path: root/csharp/ProtocolBuffers
diff options
context:
space:
mode:
authorJon Skeet <skeet@pobox.com>2008-08-14 20:35:20 +0100
committerJon Skeet <skeet@pobox.com>2008-08-14 20:35:20 +0100
commitb84310e1101af3c442e102f4c9ed03f3eff105fb (patch)
tree5f83c80efb0b5065610b643995fad5572731cc9b /csharp/ProtocolBuffers
parent023d7398d6227e9613afcfe12d3d47454b0a9de5 (diff)
downloadprotobuf-b84310e1101af3c442e102f4c9ed03f3eff105fb.tar.gz
protobuf-b84310e1101af3c442e102f4c9ed03f3eff105fb.tar.bz2
protobuf-b84310e1101af3c442e102f4c9ed03f3eff105fb.zip
Field accessor implementations complete (hopefully)
Diffstat (limited to 'csharp/ProtocolBuffers')
-rw-r--r--csharp/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs4
-rw-r--r--csharp/ProtocolBuffers/Descriptors/EnumDescriptor.cs2
-rw-r--r--csharp/ProtocolBuffers/FieldAccess/Delegates.cs3
-rw-r--r--csharp/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs52
-rw-r--r--csharp/ProtocolBuffers/FieldAccess/RepeatedEnumAccessor.cs45
-rw-r--r--csharp/ProtocolBuffers/FieldAccess/RepeatedMessageAccessor.cs58
-rw-r--r--csharp/ProtocolBuffers/FieldAccess/RepeatedPrimitiveAccessor.cs102
-rw-r--r--csharp/ProtocolBuffers/FieldAccess/SingleEnumAccessor.cs39
-rw-r--r--csharp/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs52
-rw-r--r--csharp/ProtocolBuffers/FieldAccess/SinglePrimitiveAccessor.cs79
-rw-r--r--csharp/ProtocolBuffers/IMessage.cs5
-rw-r--r--csharp/ProtocolBuffers/ProtocolBuffers.csproj6
12 files changed, 437 insertions, 10 deletions
diff --git a/csharp/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs b/csharp/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs
index becb23cc..4b92791a 100644
--- a/csharp/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs
+++ b/csharp/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs
@@ -84,7 +84,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x10, 0x0b, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x59, 0x54,
0x45, 0x53, 0x10, 0x0c, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10,
0x0d, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x4e, 0x55, 0x4d, 0x10, 0x0e, 0x12, 0x11, 0x0a, 0x0d,
- 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x46, 0x49, 0x58, 0x45, 0x44, 0x33, 0x32, 0x10, 0x0f, 0x12, 0x11, 0x0a, 0x0d, 0x54,
+ 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x46, 0x49, 0x58, 0x45, 0x44, 0x33, 0x32, 0x10, 0x14, 0x12, 0x11, 0x0a, 0x0d, 0x54,
0x59, 0x50, 0x45, 0x5f, 0x53, 0x46, 0x49, 0x58, 0x45, 0x44, 0x36, 0x34, 0x10, 0x10, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59,
0x50, 0x45, 0x5f, 0x53, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x11, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f,
0x53, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10, 0x12, 0x22, 0x43, 0x0a, 0x05, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x12, 0x0a,
@@ -1908,7 +1908,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
[pbd::EnumDescriptorIndex(13)]
TYPE_ENUM = 14,
[pbd::EnumDescriptorIndex(14)]
- TYPE_SFIXED32 = 15,
+ TYPE_SFIXED32 = 20,
[pbd::EnumDescriptorIndex(15)]
TYPE_SFIXED64 = 16,
[pbd::EnumDescriptorIndex(16)]
diff --git a/csharp/ProtocolBuffers/Descriptors/EnumDescriptor.cs b/csharp/ProtocolBuffers/Descriptors/EnumDescriptor.cs
index 3dccc287..83807582 100644
--- a/csharp/ProtocolBuffers/Descriptors/EnumDescriptor.cs
+++ b/csharp/ProtocolBuffers/Descriptors/EnumDescriptor.cs
@@ -43,8 +43,6 @@ namespace Google.ProtocolBuffers.Descriptors {
/// Finds an enum value by number. If multiple enum values have the
/// same number, this returns the first defined value with that number.
/// </summary>
- /// <param name="number"></param>
- /// <returns></returns>
internal EnumValueDescriptor FindValueByNumber(int number) {
return File.DescriptorPool.FindEnumValueByNumber(this, number);
}
diff --git a/csharp/ProtocolBuffers/FieldAccess/Delegates.cs b/csharp/ProtocolBuffers/FieldAccess/Delegates.cs
index 3dc0445d..000ae250 100644
--- a/csharp/ProtocolBuffers/FieldAccess/Delegates.cs
+++ b/csharp/ProtocolBuffers/FieldAccess/Delegates.cs
@@ -7,6 +7,5 @@ namespace Google.ProtocolBuffers.FieldAccess {
/// Declarations of delegate types used for field access. Can't
/// use Func and Action (other than one parameter) as we can't guarantee .NET 3.5.
/// </summary>
- delegate bool HasFunction<TMessage>(TMessage message);
-
+ internal delegate bool HasFunction<TMessage>(TMessage message);
}
diff --git a/csharp/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs b/csharp/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs
index 7fec437f..231b974c 100644
--- a/csharp/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs
+++ b/csharp/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs
@@ -2,20 +2,68 @@
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers.FieldAccess {
+ /// <summary>
+ /// Provides access to fields in generated messages via reflection.
+ /// This type is public to allow it to be used by generated messages, which
+ /// create appropriate instances in the .proto file description class.
+ /// TODO(jonskeet): See if we can hide it somewhere...
+ /// </summary>
public class FieldAccessorTable {
+ readonly IFieldAccessor[] accessors;
+
readonly MessageDescriptor descriptor;
public MessageDescriptor Descriptor {
get { return descriptor; }
}
- public FieldAccessorTable(MessageDescriptor descriptor, String[] pascalCaseFieldNames, Type messageType, Type builderType) {
+ /// <summary>
+ /// Constructs a FieldAccessorTable for a particular message class.
+ /// Only one FieldAccessorTable should be constructed per class.
+ /// </summary>
+ /// <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>
+ /// <param name="messageType">The .NET type representing the message</param>
+ /// <param name="builderType">The .NET type representing the message's builder type</param>
+ public FieldAccessorTable(MessageDescriptor descriptor, String[] propertyNames, Type messageType, Type builderType) {
this.descriptor = descriptor;
+ accessors = new IFieldAccessor[descriptor.Fields.Count];
+ for (int i=0; i < accessors.Length; i++) {
+ accessors[i] = CreateAccessor(descriptor.Fields[i], propertyNames[i], messageType, builderType);
+ }
+ }
+
+ /// <summary>
+ /// Creates an accessor for a single field
+ /// </summary>
+ private static IFieldAccessor CreateAccessor(FieldDescriptor field, string name, Type messageType, Type builderType) {
+ if (field.IsRepeated) {
+ switch (field.MappedType) {
+ case MappedType.Message: return new RepeatedMessageAccessor(name, messageType, builderType);
+ case MappedType.Enum: return new RepeatedEnumAccessor(field, name, messageType, builderType);
+ default: return new RepeatedPrimitiveAccessor(name, messageType, builderType);
+ }
+ } else {
+ switch (field.MappedType) {
+ case MappedType.Message: return new SingleMessageAccessor(name, messageType, builderType);
+ case MappedType.Enum: return new SingleEnumAccessor(field, name, messageType, builderType);
+ default: return new SinglePrimitiveAccessor(name, messageType, builderType);
+ }
+ }
}
internal IFieldAccessor this[FieldDescriptor field] {
- get { return null; }
+ get {
+ if (field.ContainingType != descriptor) {
+ throw new ArgumentException("FieldDescriptor does not match message type.");
+ } else if (field.IsExtension) {
+ // If this type had extensions, it would subclass ExtendableMessage,
+ // which overrides the reflection interface to handle extensions.
+ throw new ArgumentException("This type does not have extensions.");
+ }
+ return accessors[field.Index];
+ }
}
}
}
diff --git a/csharp/ProtocolBuffers/FieldAccess/RepeatedEnumAccessor.cs b/csharp/ProtocolBuffers/FieldAccess/RepeatedEnumAccessor.cs
new file mode 100644
index 00000000..48724192
--- /dev/null
+++ b/csharp/ProtocolBuffers/FieldAccess/RepeatedEnumAccessor.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using Google.ProtocolBuffers.Collections;
+using Google.ProtocolBuffers.Descriptors;
+
+namespace Google.ProtocolBuffers.FieldAccess {
+
+ /// <summary>
+ /// Accessor for a repeated enum field.
+ /// </summary>
+ internal sealed class RepeatedEnumAccessor : RepeatedPrimitiveAccessor {
+
+ private readonly EnumDescriptor enumDescriptor;
+
+ internal RepeatedEnumAccessor(FieldDescriptor field, string name, Type messageType, Type builderType)
+ : base(name, messageType, builderType) {
+
+ enumDescriptor = field.EnumType;
+ }
+
+ public override object GetValue(IMessage message) {
+ List<EnumValueDescriptor> ret = new List<EnumValueDescriptor>();
+ foreach (int rawValue in (IEnumerable) base.GetValue(message)) {
+ ret.Add(enumDescriptor.FindValueByNumber(rawValue));
+ }
+ return Lists.AsReadOnly(ret);
+ }
+
+ public override object GetRepeatedValue(IMessage message, int index) {
+ // Note: This relies on the fact that the CLR allows unboxing from an enum to
+ // its underlying value
+ int rawValue = (int) base.GetRepeatedValue(message, index);
+ return enumDescriptor.FindValueByNumber(rawValue);
+ }
+
+ public override void AddRepeated(IBuilder builder, object value) {
+ base.AddRepeated(builder, ((EnumValueDescriptor) value).Number);
+ }
+
+ public override void SetRepeated(IBuilder builder, int index, object value) {
+ base.SetRepeated(builder, index, ((EnumValueDescriptor) value).Number);
+ }
+ }
+}
diff --git a/csharp/ProtocolBuffers/FieldAccess/RepeatedMessageAccessor.cs b/csharp/ProtocolBuffers/FieldAccess/RepeatedMessageAccessor.cs
new file mode 100644
index 00000000..6f40938e
--- /dev/null
+++ b/csharp/ProtocolBuffers/FieldAccess/RepeatedMessageAccessor.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Reflection;
+using Google.ProtocolBuffers.Descriptors;
+
+namespace Google.ProtocolBuffers.FieldAccess {
+
+ /// <summary>
+ /// Accessor for a repeated message field.
+ ///
+ /// TODO(jonskeet): Try to extract the commonality between this and SingleMessageAccessor.
+ /// We almost want multiple inheritance...
+ /// </summary>
+ internal sealed class RepeatedMessageAccessor : RepeatedPrimitiveAccessor {
+
+ /// <summary>
+ /// The static method to create a builder for the property type. For example,
+ /// in a message type "Foo", a field called "bar" might be of type "Baz". This
+ /// method is Baz.CreateBuilder.
+ /// </summary>
+ private readonly MethodInfo createBuilderMethod;
+
+ internal RepeatedMessageAccessor(string name, Type messageType, Type builderType)
+ : base(name, messageType, builderType) {
+ createBuilderMethod = ClrType.GetMethod("CreateBuilder", BindingFlags.Public | BindingFlags.Static);
+ if (createBuilderMethod == null) {
+ throw new ArgumentException("No public static CreateBuilder method declared in " + ClrType.Name);
+ }
+ }
+
+ /// <summary>
+ /// Creates a message of the appropriate CLR type from the given value,
+ /// which may already be of the right type or may be a dynamic message.
+ /// </summary>
+ private object CoerceType(object value) {
+
+ // If it's already of the right type, we're done
+ if (ClrType.IsInstanceOfType(value)) {
+ return value;
+ }
+
+ // No... so let's create a builder of the right type, and merge the value in.
+ IMessage message = (IMessage) value;
+ return CreateBuilder().MergeFrom(message).Build();
+ }
+
+ public override void SetRepeated(IBuilder builder, int index, object value) {
+ base.SetRepeated(builder, index, CoerceType(value));
+ }
+
+ public override IBuilder CreateBuilder() {
+ return (IBuilder) createBuilderMethod.Invoke(null, null);
+ }
+
+ public override void AddRepeated(IBuilder builder, object value) {
+ base.AddRepeated(builder, CoerceType(value));
+ }
+ }
+}
diff --git a/csharp/ProtocolBuffers/FieldAccess/RepeatedPrimitiveAccessor.cs b/csharp/ProtocolBuffers/FieldAccess/RepeatedPrimitiveAccessor.cs
new file mode 100644
index 00000000..232a1e28
--- /dev/null
+++ b/csharp/ProtocolBuffers/FieldAccess/RepeatedPrimitiveAccessor.cs
@@ -0,0 +1,102 @@
+using System;
+using System.Collections;
+using System.Reflection;
+using Google.ProtocolBuffers.Descriptors;
+
+namespace Google.ProtocolBuffers.FieldAccess {
+ /// <summary>
+ /// Accesor for a repeated field of type int, ByteString etc.
+ /// </summary>
+ internal class RepeatedPrimitiveAccessor : IFieldAccessor {
+
+ private readonly PropertyInfo messageProperty;
+ private readonly PropertyInfo builderProperty;
+ private readonly PropertyInfo hasProperty;
+ private readonly PropertyInfo countProperty;
+ private readonly MethodInfo clearMethod;
+ private readonly MethodInfo addMethod;
+ private readonly MethodInfo getElementMethod;
+ private readonly MethodInfo setElementMethod;
+
+ /// <summary>
+ /// The CLR type of the field (int, the enum type, ByteString, the message etc).
+ /// This is taken from the return type of the method used to retrieve a single
+ /// value.
+ /// </summary>
+ protected Type ClrType {
+ get { return getElementMethod.ReturnType; }
+ }
+
+ internal RepeatedPrimitiveAccessor(string name, Type messageType, Type builderType) {
+ messageProperty = messageType.GetProperty(name + "List");
+ builderProperty = builderType.GetProperty(name + "List");
+ hasProperty = messageType.GetProperty("Has" + name);
+ countProperty = messageType.GetProperty(name + "Count");
+ clearMethod = builderType.GetMethod("Clear" + name);
+ addMethod = builderType.GetMethod("Add" + name);
+ getElementMethod = messageType.GetMethod("Get" + name, new Type[] { typeof(int) });
+ setElementMethod = builderType.GetMethod("Set" + name, new Type[] { typeof(int) });
+ if (messageProperty == null
+ || builderProperty == null
+ || hasProperty == null
+ || countProperty == null
+ || clearMethod == null
+ || addMethod == null
+ || getElementMethod == null
+ || setElementMethod == null) {
+ throw new ArgumentException("Not all required properties/methods available");
+ }
+ }
+
+ public bool Has(IMessage message) {
+ throw new InvalidOperationException();
+ }
+
+ public virtual IBuilder CreateBuilder() {
+ throw new InvalidOperationException();
+ }
+
+ public virtual object GetValue(IMessage message) {
+ return messageProperty.GetValue(message, null);
+ }
+
+ public void SetValue(IBuilder builder, object value) {
+ // Add all the elements individually. This serves two purposes:
+ // 1) Verifies that each element has the correct type.
+ // 2) Insures that the caller cannot modify the list later on and
+ // have the modifications be reflected in the message.
+ Clear(builder);
+ foreach (object element in (IEnumerable) value) {
+ AddRepeated(builder, element);
+ }
+ }
+
+ public void Clear(IBuilder builder) {
+ clearMethod.Invoke(builder, null);
+ }
+
+ public int GetRepeatedCount(IMessage message) {
+ return (int) countProperty.GetValue(null, null);
+ }
+
+ public virtual object GetRepeatedValue(IMessage message, int index) {
+ return getElementMethod.Invoke(message, new object[] {index } );
+ }
+
+ public virtual void SetRepeated(IBuilder builder, int index, object value) {
+ setElementMethod.Invoke(builder, new object[] {index, value} );
+ }
+
+ public virtual void AddRepeated(IBuilder builder, object value) {
+ addMethod.Invoke(builder, new object[] { value });
+ }
+
+ /// <summary>
+ /// The builder class's accessor already builds a read-only wrapper for
+ /// us, which is exactly what we want.
+ /// </summary>
+ public object GetRepeatedWrapper(IBuilder builder) {
+ return builderProperty.GetValue(builder, null);
+ }
+ }
+} \ No newline at end of file
diff --git a/csharp/ProtocolBuffers/FieldAccess/SingleEnumAccessor.cs b/csharp/ProtocolBuffers/FieldAccess/SingleEnumAccessor.cs
new file mode 100644
index 00000000..0e9e68f8
--- /dev/null
+++ b/csharp/ProtocolBuffers/FieldAccess/SingleEnumAccessor.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using Google.ProtocolBuffers.Descriptors;
+
+namespace Google.ProtocolBuffers.FieldAccess {
+ /// <summary>
+ /// Accessor for fields representing a non-repeated enum value.
+ /// </summary>
+ internal sealed class SingleEnumAccessor : SinglePrimitiveAccessor {
+
+ private readonly EnumDescriptor enumDescriptor;
+
+ internal SingleEnumAccessor(FieldDescriptor field, string name, Type messageType, Type builderType)
+ : base(name, messageType, builderType) {
+ enumDescriptor = field.EnumType;
+ }
+
+ /// <summary>
+ /// Returns an EnumValueDescriptor representing the value in the builder.
+ /// Note that if an enum has multiple values for the same number, the descriptor
+ /// for the first value with that number will be returned.
+ /// </summary>
+ public override object GetValue(IMessage message) {
+ // Note: This relies on the fact that the CLR allows unboxing from an enum to
+ // its underlying value
+ int rawValue = (int) base.GetValue(message);
+ return enumDescriptor.FindValueByNumber(rawValue);
+ }
+
+ /// <summary>
+ /// Sets the value as an enum (via an int) in the builder,
+ /// from an EnumValueDescriptor parameter.
+ /// </summary>
+ public override void SetValue(IBuilder builder, object value) {
+ EnumValueDescriptor valueDescriptor = (EnumValueDescriptor) value;
+ base.SetValue(builder, valueDescriptor.Number);
+ }
+ }
+} \ No newline at end of file
diff --git a/csharp/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs b/csharp/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs
new file mode 100644
index 00000000..c9647b07
--- /dev/null
+++ b/csharp/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Reflection;
+using Google.ProtocolBuffers.Descriptors;
+
+namespace Google.ProtocolBuffers.FieldAccess {
+ /// <summary>
+ /// Accessor for fields representing a non-repeated message value.
+ /// </summary>
+ internal sealed class SingleMessageAccessor : SinglePrimitiveAccessor {
+
+ /// <summary>
+ /// The static method to create a builder for the property type. For example,
+ /// in a message type "Foo", a field called "bar" might be of type "Baz". This
+ /// method is Baz.CreateBuilder.
+ /// </summary>
+ private readonly MethodInfo createBuilderMethod;
+
+
+ internal SingleMessageAccessor(string name, Type messageType, Type builderType)
+ : base(name, messageType, builderType) {
+
+ createBuilderMethod = ClrType.GetMethod("CreateBuilder", BindingFlags.Public | BindingFlags.Static);
+ if (createBuilderMethod == null) {
+ throw new ArgumentException("No public static CreateBuilder method declared in " + ClrType.Name);
+ }
+ }
+
+ /// <summary>
+ /// Creates a message of the appropriate CLR type from the given value,
+ /// which may already be of the right type or may be a dynamic message.
+ /// </summary>
+ private object CoerceType(object value) {
+
+ // If it's already of the right type, we're done
+ if (ClrType.IsInstanceOfType(value)) {
+ return value;
+ }
+
+ // No... so let's create a builder of the right type, and merge the value in.
+ IMessage message = (IMessage) value;
+ return CreateBuilder().MergeFrom(message).Build();
+ }
+
+ public override void SetValue(IBuilder builder, object value) {
+ base.SetValue(builder, CoerceType(value));
+ }
+
+ public override IBuilder CreateBuilder() {
+ return (IBuilder) createBuilderMethod.Invoke(null, null);
+ }
+ }
+} \ No newline at end of file
diff --git a/csharp/ProtocolBuffers/FieldAccess/SinglePrimitiveAccessor.cs b/csharp/ProtocolBuffers/FieldAccess/SinglePrimitiveAccessor.cs
new file mode 100644
index 00000000..4878e79b
--- /dev/null
+++ b/csharp/ProtocolBuffers/FieldAccess/SinglePrimitiveAccessor.cs
@@ -0,0 +1,79 @@
+using System;
+using System.Reflection;
+using Google.ProtocolBuffers.Descriptors;
+
+namespace Google.ProtocolBuffers.FieldAccess {
+ /// <summary>
+ /// Access for a non-repeated field of a "primitive" type (i.e. not another message or an enum).
+ /// </summary>
+ internal class SinglePrimitiveAccessor : IFieldAccessor {
+
+ private readonly PropertyInfo messageProperty;
+ private readonly PropertyInfo builderProperty;
+ private readonly PropertyInfo hasProperty;
+ private readonly MethodInfo clearMethod;
+
+ /// <summary>
+ /// The CLR type of the field (int, the enum type, ByteString, the message etc).
+ /// As declared by the property.
+ /// </summary>
+ protected Type ClrType {
+ get { return messageProperty.PropertyType; }
+ }
+
+ internal SinglePrimitiveAccessor(string name, Type messageType, Type builderType) {
+ messageProperty = messageType.GetProperty(name);
+ builderProperty = builderType.GetProperty(name);
+ hasProperty = messageType.GetProperty("Has" + name);
+ clearMethod = builderType.GetMethod("Clear" + name);
+ if (messageProperty == null || builderProperty == null || hasProperty == null || clearMethod == null) {
+ throw new ArgumentException("Not all required properties/methods available");
+ }
+ }
+
+ public bool Has(IMessage message) {
+ return (bool) hasProperty.GetValue(message, null);
+ }
+
+ public void Clear(IBuilder builder) {
+ clearMethod.Invoke(builder, null);
+ }
+
+ /// <summary>
+ /// Only valid for message types - this implementation throws InvalidOperationException.
+ /// </summary>
+ public virtual IBuilder CreateBuilder() {
+ throw new InvalidOperationException();
+ }
+
+ public virtual object GetValue(IMessage message) {
+ return messageProperty.GetValue(message, null);
+ }
+
+ public virtual void SetValue(IBuilder builder, object value) {
+ builderProperty.SetValue(builder, value, null);
+ }
+
+ #region Methods only related to repeated values
+ public int GetRepeatedCount(IMessage message) {
+ throw new InvalidOperationException();
+ }
+
+ public object GetRepeatedValue(IMessage message, int index) {
+ throw new InvalidOperationException();
+ }
+
+ public void SetRepeated(IBuilder builder, int index, object value) {
+ throw new InvalidOperationException();
+ }
+
+ public void AddRepeated(IBuilder builder, object value) {
+ throw new InvalidOperationException();
+ }
+
+ public object GetRepeatedWrapper(IBuilder builder) {
+ throw new InvalidOperationException();
+ }
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/csharp/ProtocolBuffers/IMessage.cs b/csharp/ProtocolBuffers/IMessage.cs
index da9aa9f3..abb29f72 100644
--- a/csharp/ProtocolBuffers/IMessage.cs
+++ b/csharp/ProtocolBuffers/IMessage.cs
@@ -57,8 +57,9 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Obtains the value of the given field, or the default value if
- /// it isn't set. For value type fields including enums, the boxed
- /// value is returned. For embedded message fields, the sub-message
+ /// it isn't set. For value type fields, the boxed value is returned.
+ /// For enum fields, the EnumValueDescriptor for the enum is returned.
+ /// For embedded message fields, the sub-message
/// is returned. For repeated fields, an IList&lt;T&gt; is returned.
/// </summary>
object this[FieldDescriptor field] { get; }
diff --git a/csharp/ProtocolBuffers/ProtocolBuffers.csproj b/csharp/ProtocolBuffers/ProtocolBuffers.csproj
index f0fb7ab3..706d2eaf 100644
--- a/csharp/ProtocolBuffers/ProtocolBuffers.csproj
+++ b/csharp/ProtocolBuffers/ProtocolBuffers.csproj
@@ -69,9 +69,15 @@
<Compile Include="Descriptors\ServiceDescriptor.cs" />
<Compile Include="ExtensionInfo.cs" />
<Compile Include="ExtensionRegistry.cs" />
+ <Compile Include="FieldAccess\SingleEnumAccessor.cs" />
+ <Compile Include="FieldAccess\SingleMessageAccessor.cs" />
+ <Compile Include="FieldAccess\SinglePrimitiveAccessor.cs" />
+ <Compile Include="FieldAccess\RepeatedPrimitiveAccessor.cs" />
+ <Compile Include="FieldAccess\RepeatedEnumAccessor.cs" />
<Compile Include="FieldAccess\Delegates.cs" />
<Compile Include="FieldAccess\IFieldAccessor.cs" />
<Compile Include="FieldAccess\FieldAccessorTable.cs" />
+ <Compile Include="FieldAccess\RepeatedMessageAccessor.cs" />
<Compile Include="FieldSet.cs" />
<Compile Include="GeneratedBuilder.cs" />
<Compile Include="GeneratedExtension.cs" />