aboutsummaryrefslogtreecommitdiff
path: root/csharp/ProtocolBuffers/GeneratedExtension.cs
blob: 667b4531d283c47748f5b69e17ebedfc155b0548 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
using Google.ProtocolBuffers.Descriptors;
using System;
using System.Collections.Generic;
using System.Reflection;

namespace Google.ProtocolBuffers {

  public static class GeneratedExtension {

    public static GeneratedExtension<TContainer, TExtension> CreateExtension<TContainer, TExtension>(FieldDescriptor descriptor)
        where TContainer : IMessage<TContainer> {
      if (descriptor.IsRepeated) {
        throw new ArgumentException("Must call CreateRepeatedGeneratedExtension() for repeated types.");
      }
      return new GeneratedExtension<TContainer, TExtension>(descriptor);
    }

    public static GeneratedExtension<TContainer, IList<TExtension>> CreateRepeatedExtension<TContainer, TExtension>(FieldDescriptor descriptor) 
        where TContainer : IMessage<TContainer> {
      if (descriptor.IsRepeated) {
        throw new ArgumentException("Must call CreateRepeatedGeneratedExtension() for repeated types.");
      }
      return new GeneratedExtension<TContainer, IList<TExtension>>(descriptor);
    }
  }

  /// <summary>
  /// Base class for all generated extensions.
  /// </summary>
  /// <remarks>
  /// The protocol compiler generates a static singleton instance of this
  /// class for each extension. For exmaple, imagine a .proto file with:
  /// <code>
  /// message Foo {
  ///   extensions 1000 to max
  /// }
  /// 
  /// extend Foo {
  ///   optional int32 bar;
  /// }
  /// </code>
  /// Then MyProto.Foo.Bar has type GeneratedExtension&lt;MyProto.Foo,int&gt;.
  /// <para />
  /// In general, users should ignore the details of this type, and
  /// simply use the static singletons as parmaeters to the extension accessors
  /// in ExtendableMessage and ExtendableBuilder.
  /// </remarks>
  public class GeneratedExtension<TContainer, TExtension> where TContainer : IMessage<TContainer> {
    private readonly IMessage messageDefaultInstance;
    private readonly FieldDescriptor descriptor;

    internal GeneratedExtension(FieldDescriptor descriptor) {
      if (!descriptor.IsExtension) {
        throw new ArgumentException("GeneratedExtension given a regular (non-extension) field.");
      }

      this.descriptor = descriptor;

      switch (descriptor.MappedType) {
        case MappedType.Message:
          PropertyInfo defaultInstanceProperty = typeof(TExtension)
              .GetProperty("DefaultInstance", BindingFlags.Static | BindingFlags.Public);
          if (defaultInstanceProperty == null) {
            throw new ArgumentException("No public static DefaultInstance property for type " + typeof(TExtension).Name);
          }
          messageDefaultInstance = (IMessage) defaultInstanceProperty.GetValue(null, null);
          break;
        case MappedType.Enum:
          // FIXME(jonskeet): May not need this
          //enumValueOf = getMethodOrDie(type, "valueOf",
            //                           EnumValueDescriptor.class);
          //enumGetValueDescriptor = getMethodOrDie(type, "getValueDescriptor");
          messageDefaultInstance = null;
          break;
        default:
          messageDefaultInstance = null;
          break;
      }
    }

    public FieldDescriptor Descriptor {
      get { return descriptor; }
    }

    public IMessage MessageDefaultInstance {
      get { return messageDefaultInstance; }
    }

    internal object SingularFromReflectionType(object p) {
      throw new System.NotImplementedException();
    }

    internal object FromReflectionType(object value) {
      throw new System.NotImplementedException();
    }
  }
}