aboutsummaryrefslogtreecommitdiff
path: root/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs
diff options
context:
space:
mode:
Diffstat (limited to 'csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs')
-rw-r--r--csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs33
1 files changed, 24 insertions, 9 deletions
diff --git a/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs b/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs
index bbac2173..d541570f 100644
--- a/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs
@@ -48,6 +48,7 @@ namespace Google.Protobuf.Reflection
private readonly Action<IMessage, object> setValueDelegate;
private readonly Action<IMessage> clearDelegate;
+ private readonly Func<IMessage, bool> hasDelegate;
internal SingleFieldAccessor(PropertyInfo property, FieldDescriptor descriptor) : base(property, descriptor)
{
@@ -56,16 +57,25 @@ namespace Google.Protobuf.Reflection
throw new ArgumentException("Not all required properties/methods available");
}
setValueDelegate = ReflectionUtil.CreateActionIMessageObject(property.GetSetMethod());
+ if (descriptor.File.Proto.Syntax == "proto2")
+ {
+ MethodInfo hasMethod = property.DeclaringType.GetRuntimeProperty("Has" + property.Name).GetMethod;
+ hasDelegate = ReflectionUtil.CreateFuncIMessageBool(hasMethod ?? throw new ArgumentException("Not all required properties/methods are available"));
+ MethodInfo clearMethod = property.DeclaringType.GetRuntimeMethod("Clear" + property.Name, ReflectionUtil.EmptyTypes);
+ clearDelegate = ReflectionUtil.CreateActionIMessage(clearMethod ?? throw new ArgumentException("Not all required properties/methods are available"));
+ }
+ else
+ {
+ hasDelegate = (_) => throw new InvalidOperationException("HasValue is not implemented for proto3 fields"); var clrType = property.PropertyType;
- var clrType = property.PropertyType;
-
- // TODO: Validate that this is a reasonable single field? (Should be a value type, a message type, or string/ByteString.)
- object defaultValue =
- descriptor.FieldType == FieldType.Message ? null
- : clrType == typeof(string) ? ""
- : clrType == typeof(ByteString) ? ByteString.Empty
- : Activator.CreateInstance(clrType);
- clearDelegate = message => SetValue(message, defaultValue);
+ // TODO: Validate that this is a reasonable single field? (Should be a value type, a message type, or string/ByteString.)
+ object defaultValue =
+ descriptor.FieldType == FieldType.Message ? null
+ : clrType == typeof(string) ? ""
+ : clrType == typeof(ByteString) ? ByteString.Empty
+ : Activator.CreateInstance(clrType);
+ clearDelegate = message => SetValue(message, defaultValue);
+ }
}
public override void Clear(IMessage message)
@@ -73,6 +83,11 @@ namespace Google.Protobuf.Reflection
clearDelegate(message);
}
+ public override bool HasValue(IMessage message)
+ {
+ return hasDelegate(message);
+ }
+
public override void SetValue(IMessage message, object value)
{
setValueDelegate(message, value);