|
@@ -30,62 +30,57 @@
|
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
#endregion
|
|
|
|
|
|
+using Google.Protobuf.Descriptors;
|
|
|
+using System;
|
|
|
+using System.Reflection;
|
|
|
+
|
|
|
namespace Google.Protobuf.FieldAccess
|
|
|
{
|
|
|
- // TODO(jonskeet): Add "new" oneof API support
|
|
|
-
|
|
|
/// <summary>
|
|
|
- /// Access for an oneof
|
|
|
+ /// Reflection access for a oneof, allowing clear and "get case" actions.
|
|
|
/// </summary>
|
|
|
- internal class OneofAccessor<TMessage> where TMessage : IMessage<TMessage>
|
|
|
+ public sealed class OneofAccessor
|
|
|
{
|
|
|
- /*
|
|
|
- private readonly Func<TMessage, object> caseDelegate;
|
|
|
- private readonly Func<TBuilder, IBuilder> clearDelegate;
|
|
|
- private MessageDescriptor descriptor;
|
|
|
+ private readonly Func<object, int> caseDelegate;
|
|
|
+ private readonly Action<object> clearDelegate;
|
|
|
+ private OneofDescriptor descriptor;
|
|
|
|
|
|
- internal OneofAccessor(MessageDescriptor descriptor, string name)
|
|
|
+ internal OneofAccessor(Type type, string propertyName, OneofDescriptor descriptor)
|
|
|
{
|
|
|
- this.descriptor = descriptor;
|
|
|
- MethodInfo clearMethod = typeof(TBuilder).GetMethod("Clear" + name);
|
|
|
- PropertyInfo caseProperty = typeof(TMessage).GetProperty(name + "Case");
|
|
|
- if (clearMethod == null || caseProperty == null)
|
|
|
+ PropertyInfo property = type.GetProperty(propertyName + "Case");
|
|
|
+ if (property == null || !property.CanRead)
|
|
|
{
|
|
|
- throw new ArgumentException("Not all required properties/methods available for oneof");
|
|
|
+ throw new ArgumentException("Not all required properties/methods available");
|
|
|
}
|
|
|
-
|
|
|
+ this.descriptor = descriptor;
|
|
|
+ caseDelegate = ReflectionUtil.CreateFuncObjectT<int>(property.GetGetMethod());
|
|
|
|
|
|
- clearDelegate = ReflectionUtil.CreateDelegateFunc<TBuilder, IBuilder>(clearMethod);
|
|
|
- caseDelegate = ReflectionUtil.CreateUpcastDelegate<TMessage>(caseProperty.GetGetMethod());
|
|
|
+ this.descriptor = descriptor;
|
|
|
+ MethodInfo clearMethod = type.GetMethod("Clear" + propertyName);
|
|
|
+ clearDelegate = ReflectionUtil.CreateActionObject(clearMethod);
|
|
|
}
|
|
|
|
|
|
- /// <summary>
|
|
|
- /// Indicates whether the specified message has set any field in the oneof.
|
|
|
- /// </summary>
|
|
|
- public bool Has(TMessage message)
|
|
|
- {
|
|
|
- return ((int) caseDelegate(message) != 0);
|
|
|
- }
|
|
|
+ public OneofDescriptor Descriptor { get { return descriptor; } }
|
|
|
|
|
|
/// <summary>
|
|
|
- /// Clears the oneof in the specified builder.
|
|
|
+ /// Clears the oneof in the specified message.
|
|
|
/// </summary>
|
|
|
- public void Clear(TBuilder builder)
|
|
|
+ public void Clear(object message)
|
|
|
{
|
|
|
- clearDelegate(builder);
|
|
|
+ clearDelegate(message);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// Indicates which field in the oneof is set for specified message
|
|
|
/// </summary>
|
|
|
- public virtual FieldDescriptor GetOneofFieldDescriptor(TMessage message)
|
|
|
+ public FieldDescriptor GetCaseFieldDescriptor(object message)
|
|
|
{
|
|
|
- int fieldNumber = (int) caseDelegate(message);
|
|
|
+ int fieldNumber = caseDelegate(message);
|
|
|
if (fieldNumber > 0)
|
|
|
{
|
|
|
- return descriptor.FindFieldByNumber(fieldNumber);
|
|
|
+ return descriptor.ContainingType.FindFieldByNumber(fieldNumber);
|
|
|
}
|
|
|
return null;
|
|
|
- }*/
|
|
|
+ }
|
|
|
}
|
|
|
}
|