diff options
Diffstat (limited to 'csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs')
-rw-r--r-- | csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs | 33 |
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); |