aboutsummaryrefslogtreecommitdiff
path: root/csharp/ProtocolBuffers/FieldAccess
diff options
context:
space:
mode:
Diffstat (limited to 'csharp/ProtocolBuffers/FieldAccess')
-rw-r--r--csharp/ProtocolBuffers/FieldAccess/Delegates.cs11
-rw-r--r--csharp/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs30
-rw-r--r--csharp/ProtocolBuffers/FieldAccess/IFieldAccessor.cs14
-rw-r--r--csharp/ProtocolBuffers/FieldAccess/RepeatedEnumAccessor.cs10
-rw-r--r--csharp/ProtocolBuffers/FieldAccess/RepeatedMessageAccessor.cs7
-rw-r--r--csharp/ProtocolBuffers/FieldAccess/RepeatedPrimitiveAccessor.cs41
-rw-r--r--csharp/ProtocolBuffers/FieldAccess/SingleEnumAccessor.cs11
-rw-r--r--csharp/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs9
-rw-r--r--csharp/ProtocolBuffers/FieldAccess/SinglePrimitiveAccessor.cs34
9 files changed, 96 insertions, 71 deletions
diff --git a/csharp/ProtocolBuffers/FieldAccess/Delegates.cs b/csharp/ProtocolBuffers/FieldAccess/Delegates.cs
new file mode 100644
index 00000000..04b1d94c
--- /dev/null
+++ b/csharp/ProtocolBuffers/FieldAccess/Delegates.cs
@@ -0,0 +1,11 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Google.ProtocolBuffers.FieldAccess {
+
+ delegate bool HasDelegate<T>(T message);
+ delegate T ClearDelegate<T>(T builder);
+ delegate int RepeatedCountDelegate<T>(T message);
+ delegate object GetValueDelegate<T>(T message);
+}
diff --git a/csharp/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs b/csharp/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs
index 24113b41..c7f5da6d 100644
--- a/csharp/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs
+++ b/csharp/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs
@@ -23,9 +23,11 @@ namespace Google.ProtocolBuffers.FieldAccess {
/// create appropriate instances in the .proto file description class.
/// TODO(jonskeet): See if we can hide it somewhere...
/// </summary>
- public sealed class FieldAccessorTable {
+ public sealed class FieldAccessorTable<TMessage, TBuilder>
+ where TMessage : IMessage<TMessage, TBuilder>
+ where TBuilder : IBuilder<TMessage, TBuilder> {
- readonly IFieldAccessor[] accessors;
+ readonly IFieldAccessor<TMessage, TBuilder>[] accessors;
readonly MessageDescriptor descriptor;
@@ -39,36 +41,34 @@ namespace Google.ProtocolBuffers.FieldAccess {
/// </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) {
+ public FieldAccessorTable(MessageDescriptor descriptor, String[] propertyNames) {
this.descriptor = descriptor;
- accessors = new IFieldAccessor[descriptor.Fields.Count];
+ accessors = new IFieldAccessor<TMessage, TBuilder>[descriptor.Fields.Count];
for (int i=0; i < accessors.Length; i++) {
- accessors[i] = CreateAccessor(descriptor.Fields[i], propertyNames[i], messageType, builderType);
+ accessors[i] = CreateAccessor(descriptor.Fields[i], propertyNames[i]);
}
}
/// <summary>
/// Creates an accessor for a single field
/// </summary>
- private static IFieldAccessor CreateAccessor(FieldDescriptor field, string name, Type messageType, Type builderType) {
+ private static IFieldAccessor<TMessage, TBuilder> CreateAccessor(FieldDescriptor field, string name) {
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);
+ case MappedType.Message: return new RepeatedMessageAccessor<TMessage, TBuilder>(name);
+ case MappedType.Enum: return new RepeatedEnumAccessor<TMessage, TBuilder>(field, name);
+ default: return new RepeatedPrimitiveAccessor<TMessage, TBuilder>(name);
}
} 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);
+ case MappedType.Message: return new SingleMessageAccessor<TMessage, TBuilder>(name);
+ case MappedType.Enum: return new SingleEnumAccessor<TMessage, TBuilder>(field, name);
+ default: return new SinglePrimitiveAccessor<TMessage, TBuilder>(name);
}
}
}
- internal IFieldAccessor this[FieldDescriptor field] {
+ internal IFieldAccessor<TMessage, TBuilder> this[FieldDescriptor field] {
get {
if (field.ContainingType != descriptor) {
throw new ArgumentException("FieldDescriptor does not match message type.");
diff --git a/csharp/ProtocolBuffers/FieldAccess/IFieldAccessor.cs b/csharp/ProtocolBuffers/FieldAccess/IFieldAccessor.cs
index 3e47fdc6..eb57c8c9 100644
--- a/csharp/ProtocolBuffers/FieldAccess/IFieldAccessor.cs
+++ b/csharp/ProtocolBuffers/FieldAccess/IFieldAccessor.cs
@@ -21,23 +21,25 @@ namespace Google.ProtocolBuffers.FieldAccess {
/// The property descriptors for each field are created once and then cached.
/// In addition, this interface holds knowledge of repeated fields, builders etc.
/// </summary>
- internal interface IFieldAccessor {
+ internal interface IFieldAccessor<TMessage, TBuilder>
+ where TMessage : IMessage<TMessage, TBuilder>
+ where TBuilder : IBuilder<TMessage, TBuilder> {
/// <summary>
/// Indicates whether the specified message contains the field.
/// </summary>
- bool Has(IMessage message);
+ bool Has(TMessage message);
/// <summary>
/// Gets the count of the repeated field in the specified message.
/// </summary>
- int GetRepeatedCount(IMessage message);
+ int GetRepeatedCount(TMessage message);
/// <summary>
/// Clears the field in the specified builder.
/// </summary>
/// <param name="builder"></param>
- void Clear(IBuilder builder);
+ void Clear(TBuilder builder);
/// <summary>
/// Creates a builder for the type of this field (which must be a message field).
@@ -47,11 +49,11 @@ namespace Google.ProtocolBuffers.FieldAccess {
/// <summary>
/// Accessor for single fields
/// </summary>
- object GetValue(IMessage message);
+ object GetValue(TMessage message);
/// <summary>
/// Mutator for single fields
/// </summary>
- void SetValue(IBuilder builder, object value);
+ void SetValue(TBuilder builder, object value);
/// <summary>
/// Accessor for repeated fields
diff --git a/csharp/ProtocolBuffers/FieldAccess/RepeatedEnumAccessor.cs b/csharp/ProtocolBuffers/FieldAccess/RepeatedEnumAccessor.cs
index f6b273ee..3082071b 100644
--- a/csharp/ProtocolBuffers/FieldAccess/RepeatedEnumAccessor.cs
+++ b/csharp/ProtocolBuffers/FieldAccess/RepeatedEnumAccessor.cs
@@ -24,17 +24,17 @@ namespace Google.ProtocolBuffers.FieldAccess {
/// <summary>
/// Accessor for a repeated enum field.
/// </summary>
- internal sealed class RepeatedEnumAccessor : RepeatedPrimitiveAccessor {
+ internal sealed class RepeatedEnumAccessor<TMessage, TBuilder> : RepeatedPrimitiveAccessor<TMessage, TBuilder>
+ where TMessage : IMessage<TMessage, TBuilder>
+ where TBuilder : IBuilder<TMessage, TBuilder> {
private readonly EnumDescriptor enumDescriptor;
- internal RepeatedEnumAccessor(FieldDescriptor field, string name, Type messageType, Type builderType)
- : base(name, messageType, builderType) {
-
+ internal RepeatedEnumAccessor(FieldDescriptor field, string name) : base(name) {
enumDescriptor = field.EnumType;
}
- public override object GetValue(IMessage message) {
+ public override object GetValue(TMessage message) {
List<EnumValueDescriptor> ret = new List<EnumValueDescriptor>();
foreach (int rawValue in (IEnumerable) base.GetValue(message)) {
ret.Add(enumDescriptor.FindValueByNumber(rawValue));
diff --git a/csharp/ProtocolBuffers/FieldAccess/RepeatedMessageAccessor.cs b/csharp/ProtocolBuffers/FieldAccess/RepeatedMessageAccessor.cs
index d0c53dcc..f350752d 100644
--- a/csharp/ProtocolBuffers/FieldAccess/RepeatedMessageAccessor.cs
+++ b/csharp/ProtocolBuffers/FieldAccess/RepeatedMessageAccessor.cs
@@ -24,7 +24,9 @@ namespace Google.ProtocolBuffers.FieldAccess {
/// TODO(jonskeet): Try to extract the commonality between this and SingleMessageAccessor.
/// We almost want multiple inheritance...
/// </summary>
- internal sealed class RepeatedMessageAccessor : RepeatedPrimitiveAccessor {
+ internal sealed class RepeatedMessageAccessor<TMessage, TBuilder> : RepeatedPrimitiveAccessor<TMessage, TBuilder>
+ where TMessage : IMessage<TMessage, TBuilder>
+ where TBuilder : IBuilder<TMessage, TBuilder> {
/// <summary>
/// The static method to create a builder for the property type. For example,
@@ -33,8 +35,7 @@ namespace Google.ProtocolBuffers.FieldAccess {
/// </summary>
private readonly MethodInfo createBuilderMethod;
- internal RepeatedMessageAccessor(string name, Type messageType, Type builderType)
- : base(name, messageType, builderType) {
+ internal RepeatedMessageAccessor(string name) : base(name) {
createBuilderMethod = ClrType.GetMethod("CreateBuilder", new Type[0]);
if (createBuilderMethod == null) {
throw new ArgumentException("No public static CreateBuilder method declared in " + ClrType.Name);
diff --git a/csharp/ProtocolBuffers/FieldAccess/RepeatedPrimitiveAccessor.cs b/csharp/ProtocolBuffers/FieldAccess/RepeatedPrimitiveAccessor.cs
index ad44991d..39184b1f 100644
--- a/csharp/ProtocolBuffers/FieldAccess/RepeatedPrimitiveAccessor.cs
+++ b/csharp/ProtocolBuffers/FieldAccess/RepeatedPrimitiveAccessor.cs
@@ -21,12 +21,14 @@ namespace Google.ProtocolBuffers.FieldAccess {
/// <summary>
/// Accesor for a repeated field of type int, ByteString etc.
/// </summary>
- internal class RepeatedPrimitiveAccessor : IFieldAccessor {
+ internal class RepeatedPrimitiveAccessor<TMessage, TBuilder> : IFieldAccessor<TMessage, TBuilder>
+ where TMessage : IMessage<TMessage, TBuilder>
+ where TBuilder : IBuilder<TMessage, TBuilder> {
private readonly PropertyInfo messageProperty;
private readonly PropertyInfo builderProperty;
- private readonly PropertyInfo countProperty;
- private readonly MethodInfo clearMethod;
+ private readonly RepeatedCountDelegate<TMessage> countDelegate;
+ private readonly ClearDelegate<TBuilder> clearDelegate;
private readonly MethodInfo addMethod;
private readonly MethodInfo getElementMethod;
private readonly MethodInfo setElementMethod;
@@ -40,14 +42,14 @@ namespace Google.ProtocolBuffers.FieldAccess {
get { return getElementMethod.ReturnType; }
}
- internal RepeatedPrimitiveAccessor(string name, Type messageType, Type builderType) {
- messageProperty = messageType.GetProperty(name + "List");
- builderProperty = builderType.GetProperty(name + "List");
- countProperty = messageType.GetProperty(name + "Count");
- clearMethod = builderType.GetMethod("Clear" + name);
- getElementMethod = messageType.GetMethod("Get" + name, new Type[] { typeof(int) });
- addMethod = builderType.GetMethod("Add" + name, new Type[] { ClrType });
- setElementMethod = builderType.GetMethod("Set" + name, new Type[] { typeof(int), ClrType });
+ internal RepeatedPrimitiveAccessor(string name) {
+ messageProperty = typeof(TMessage).GetProperty(name + "List");
+ builderProperty = typeof(TBuilder).GetProperty(name + "List");
+ PropertyInfo countProperty = typeof(TMessage).GetProperty(name + "Count");
+ MethodInfo clearMethod = typeof(TBuilder).GetMethod("Clear" + name);
+ getElementMethod = typeof(TMessage).GetMethod("Get" + name, new Type[] { typeof(int) });
+ 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
@@ -57,9 +59,12 @@ namespace Google.ProtocolBuffers.FieldAccess {
|| setElementMethod == null) {
throw new ArgumentException("Not all required properties/methods available");
}
+ clearDelegate = (ClearDelegate<TBuilder>)Delegate.CreateDelegate(typeof(ClearDelegate<TBuilder>), clearMethod);
+ countDelegate = (RepeatedCountDelegate<TMessage>)Delegate.CreateDelegate
+ (typeof(RepeatedCountDelegate<TMessage>), countProperty.GetGetMethod());
}
- public bool Has(IMessage message) {
+ public bool Has(TMessage message) {
throw new InvalidOperationException();
}
@@ -67,11 +72,11 @@ namespace Google.ProtocolBuffers.FieldAccess {
throw new InvalidOperationException();
}
- public virtual object GetValue(IMessage message) {
+ public virtual object GetValue(TMessage message) {
return messageProperty.GetValue(message, null);
}
- public void SetValue(IBuilder builder, object value) {
+ public void SetValue(TBuilder 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
@@ -82,12 +87,12 @@ namespace Google.ProtocolBuffers.FieldAccess {
}
}
- public void Clear(IBuilder builder) {
- clearMethod.Invoke(builder, null);
+ public void Clear(TBuilder builder) {
+ clearDelegate(builder);
}
- public int GetRepeatedCount(IMessage message) {
- return (int) countProperty.GetValue(message, null);
+ public int GetRepeatedCount(TMessage message) {
+ return countDelegate(message);
}
public virtual object GetRepeatedValue(IMessage message, int index) {
diff --git a/csharp/ProtocolBuffers/FieldAccess/SingleEnumAccessor.cs b/csharp/ProtocolBuffers/FieldAccess/SingleEnumAccessor.cs
index 7db6b182..eb28160a 100644
--- a/csharp/ProtocolBuffers/FieldAccess/SingleEnumAccessor.cs
+++ b/csharp/ProtocolBuffers/FieldAccess/SingleEnumAccessor.cs
@@ -20,12 +20,13 @@ namespace Google.ProtocolBuffers.FieldAccess {
/// <summary>
/// Accessor for fields representing a non-repeated enum value.
/// </summary>
- internal sealed class SingleEnumAccessor : SinglePrimitiveAccessor {
+ internal sealed class SingleEnumAccessor<TMessage, TBuilder> : SinglePrimitiveAccessor<TMessage, TBuilder>
+ where TMessage : IMessage<TMessage, TBuilder>
+ where TBuilder : IBuilder<TMessage, TBuilder> {
private readonly EnumDescriptor enumDescriptor;
- internal SingleEnumAccessor(FieldDescriptor field, string name, Type messageType, Type builderType)
- : base(name, messageType, builderType) {
+ internal SingleEnumAccessor(FieldDescriptor field, string name) : base(name) {
enumDescriptor = field.EnumType;
}
@@ -34,7 +35,7 @@ namespace Google.ProtocolBuffers.FieldAccess {
/// 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) {
+ public override object GetValue(TMessage 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);
@@ -45,7 +46,7 @@ namespace Google.ProtocolBuffers.FieldAccess {
/// 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) {
+ public override void SetValue(TBuilder builder, object value) {
EnumValueDescriptor valueDescriptor = (EnumValueDescriptor) value;
base.SetValue(builder, valueDescriptor.Number);
}
diff --git a/csharp/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs b/csharp/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs
index 7945f461..460d450d 100644
--- a/csharp/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs
+++ b/csharp/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs
@@ -20,7 +20,9 @@ namespace Google.ProtocolBuffers.FieldAccess {
/// <summary>
/// Accessor for fields representing a non-repeated message value.
/// </summary>
- internal sealed class SingleMessageAccessor : SinglePrimitiveAccessor {
+ internal sealed class SingleMessageAccessor<TMessage, TBuilder> : SinglePrimitiveAccessor<TMessage, TBuilder>
+ where TMessage : IMessage<TMessage, TBuilder>
+ where TBuilder : IBuilder<TMessage, TBuilder> {
/// <summary>
/// The static method to create a builder for the property type. For example,
@@ -30,8 +32,7 @@ namespace Google.ProtocolBuffers.FieldAccess {
private readonly MethodInfo createBuilderMethod;
- internal SingleMessageAccessor(string name, Type messageType, Type builderType)
- : base(name, messageType, builderType) {
+ internal SingleMessageAccessor(string name) : base(name) {
createBuilderMethod = ClrType.GetMethod("CreateBuilder", new Type[0]);//BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly);
if (createBuilderMethod == null) {
@@ -55,7 +56,7 @@ namespace Google.ProtocolBuffers.FieldAccess {
return CreateBuilder().WeakMergeFrom(message).WeakBuild();
}
- public override void SetValue(IBuilder builder, object value) {
+ public override void SetValue(TBuilder builder, object value) {
base.SetValue(builder, CoerceType(value));
}
diff --git a/csharp/ProtocolBuffers/FieldAccess/SinglePrimitiveAccessor.cs b/csharp/ProtocolBuffers/FieldAccess/SinglePrimitiveAccessor.cs
index efa77047..8d12b45c 100644
--- a/csharp/ProtocolBuffers/FieldAccess/SinglePrimitiveAccessor.cs
+++ b/csharp/ProtocolBuffers/FieldAccess/SinglePrimitiveAccessor.cs
@@ -20,12 +20,14 @@ 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 {
+ internal class SinglePrimitiveAccessor<TMessage, TBuilder> : IFieldAccessor<TMessage, TBuilder>
+ where TMessage : IMessage<TMessage, TBuilder>
+ where TBuilder : IBuilder<TMessage, TBuilder> {
private readonly PropertyInfo messageProperty;
private readonly PropertyInfo builderProperty;
- private readonly PropertyInfo hasProperty;
- private readonly MethodInfo clearMethod;
+ private readonly HasDelegate<TMessage> hasDelegate;
+ private readonly ClearDelegate<TBuilder> clearDelegate;
/// <summary>
/// The CLR type of the field (int, the enum type, ByteString, the message etc).
@@ -35,22 +37,24 @@ namespace Google.ProtocolBuffers.FieldAccess {
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);
+ internal SinglePrimitiveAccessor(string name) {
+ messageProperty = typeof(TMessage).GetProperty(name);
+ builderProperty = typeof(TBuilder).GetProperty(name);
+ PropertyInfo hasProperty = typeof(TMessage).GetProperty("Has" + name);
+ MethodInfo clearMethod = typeof(TBuilder).GetMethod("Clear" + name);
if (messageProperty == null || builderProperty == null || hasProperty == null || clearMethod == null) {
throw new ArgumentException("Not all required properties/methods available");
}
+ hasDelegate = (HasDelegate<TMessage>)Delegate.CreateDelegate(typeof(HasDelegate<TMessage>), hasProperty.GetGetMethod());
+ clearDelegate = (ClearDelegate<TBuilder>)Delegate.CreateDelegate(typeof(ClearDelegate<TBuilder>), clearMethod);
}
- public bool Has(IMessage message) {
- return (bool) hasProperty.GetValue(message, null);
+ public bool Has(TMessage message) {
+ return hasDelegate(message);
}
- public void Clear(IBuilder builder) {
- clearMethod.Invoke(builder, null);
+ public void Clear(TBuilder builder) {
+ clearDelegate(builder);
}
/// <summary>
@@ -60,16 +64,16 @@ namespace Google.ProtocolBuffers.FieldAccess {
throw new InvalidOperationException();
}
- public virtual object GetValue(IMessage message) {
+ public virtual object GetValue(TMessage message) {
return messageProperty.GetValue(message, null);
}
- public virtual void SetValue(IBuilder builder, object value) {
+ public virtual void SetValue(TBuilder builder, object value) {
builderProperty.SetValue(builder, value, null);
}
#region Methods only related to repeated values
- public int GetRepeatedCount(IMessage message) {
+ public int GetRepeatedCount(TMessage message) {
throw new InvalidOperationException();
}