RepeatedMessageAccessor.cs 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. using System;
  2. using System.Reflection;
  3. using Google.ProtocolBuffers.Descriptors;
  4. namespace Google.ProtocolBuffers.FieldAccess {
  5. /// <summary>
  6. /// Accessor for a repeated message field.
  7. ///
  8. /// TODO(jonskeet): Try to extract the commonality between this and SingleMessageAccessor.
  9. /// We almost want multiple inheritance...
  10. /// </summary>
  11. internal sealed class RepeatedMessageAccessor : RepeatedPrimitiveAccessor {
  12. /// <summary>
  13. /// The static method to create a builder for the property type. For example,
  14. /// in a message type "Foo", a field called "bar" might be of type "Baz". This
  15. /// method is Baz.CreateBuilder.
  16. /// </summary>
  17. private readonly MethodInfo createBuilderMethod;
  18. internal RepeatedMessageAccessor(string name, Type messageType, Type builderType)
  19. : base(name, messageType, builderType) {
  20. createBuilderMethod = ClrType.GetMethod("CreateBuilder", new Type[0]);
  21. if (createBuilderMethod == null) {
  22. throw new ArgumentException("No public static CreateBuilder method declared in " + ClrType.Name);
  23. }
  24. }
  25. /// <summary>
  26. /// Creates a message of the appropriate CLR type from the given value,
  27. /// which may already be of the right type or may be a dynamic message.
  28. /// </summary>
  29. private object CoerceType(object value) {
  30. // If it's already of the right type, we're done
  31. if (ClrType.IsInstanceOfType(value)) {
  32. return value;
  33. }
  34. // No... so let's create a builder of the right type, and merge the value in.
  35. IMessage message = (IMessage) value;
  36. return CreateBuilder().MergeFrom(message).Build();
  37. }
  38. public override void SetRepeated(IBuilder builder, int index, object value) {
  39. base.SetRepeated(builder, index, CoerceType(value));
  40. }
  41. public override IBuilder CreateBuilder() {
  42. return (IBuilder) createBuilderMethod.Invoke(null, null);
  43. }
  44. public override void AddRepeated(IBuilder builder, object value) {
  45. base.AddRepeated(builder, CoerceType(value));
  46. }
  47. }
  48. }