diff options
author | Jon Skeet <jonskeet@google.com> | 2015-07-20 19:24:31 +0100 |
---|---|---|
committer | Jon Skeet <jonskeet@google.com> | 2015-07-21 12:59:40 +0100 |
commit | 53c399a1d65df65e9f83a70b55041a01cf8d7489 (patch) | |
tree | bf3f738dd30295dc8ceb65478b9071d6d654e144 /csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs | |
parent | 2ee4b5665520fe3245eb5e15df8bd35e0c539a07 (diff) | |
download | protobuf-53c399a1d65df65e9f83a70b55041a01cf8d7489.tar.gz protobuf-53c399a1d65df65e9f83a70b55041a01cf8d7489.tar.bz2 protobuf-53c399a1d65df65e9f83a70b55041a01cf8d7489.zip |
Revamp to reflection.
Changes in brief:
1. Descriptor is now the entry point for all reflection.
2. IReflectedMessage has gone; there's now a Descriptor property in IMessage, which is explicitly implemented (due to the static property).
3. FieldAccessorTable has gone away
4. IFieldAccessor and OneofFieldAccessor still exist; we *could* put the functionality straight into FieldDescriptor and OneofDescriptor... I'm unsure about that.
5. There's a temporary property MessageDescriptor.FieldAccessorsByFieldNumber to make the test changes small - we probably want this to go away
6. Discovery for delegates is now via attributes applied to properties and the Clear method of a oneof
I'm happy with 1-3.
4 I'm unsure about - feedback welcome.
5 will go away
6 I'm unsure about, both in design and implementation. Should we have a ProtobufMessageAttribute too? Should we find all the relevant attributes in MessageDescriptor and pass them down, to avoid an O(N^2) scenario?
Generated code changes coming in the next commit.
Diffstat (limited to 'csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs')
-rw-r--r-- | csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs | 34 |
1 files changed, 31 insertions, 3 deletions
diff --git a/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs index 1c22c460..9413cf61 100644 --- a/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs @@ -30,8 +30,10 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion +using Google.Protobuf.Collections; using System; using System.Collections.Generic; +using System.Linq; namespace Google.Protobuf.Reflection { @@ -60,11 +62,15 @@ namespace Google.Protobuf.Reflection private readonly IList<EnumDescriptor> enumTypes; private readonly IList<FieldDescriptor> fields; private readonly IList<OneofDescriptor> oneofs; + // CLR representation of the type described by this descriptor, if any. + private readonly Type generatedType; + private IDictionary<int, IFieldAccessor> fieldAccessorsByFieldNumber; - internal MessageDescriptor(DescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int typeIndex) + internal MessageDescriptor(DescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int typeIndex, IEnumerator<Type> generatedTypeIterator) : base(file, file.ComputeFullName(parent, proto.Name), typeIndex) { this.proto = proto; + generatedType = ReflectionUtil.GetNextType(generatedTypeIterator); containingType = parent; oneofs = DescriptorUtil.ConvertAndMakeReadOnly(proto.OneofDecl, @@ -73,11 +79,11 @@ namespace Google.Protobuf.Reflection nestedTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.NestedType, (type, index) => - new MessageDescriptor(type, file, this, index)); + new MessageDescriptor(type, file, this, index, generatedTypeIterator)); enumTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.EnumType, (type, index) => - new EnumDescriptor(type, file, this, index)); + new EnumDescriptor(type, file, this, index, ReflectionUtil.GetNextType(generatedTypeIterator))); // TODO(jonskeet): Sort fields first? fields = DescriptorUtil.ConvertAndMakeReadOnly(proto.Field, @@ -85,6 +91,14 @@ namespace Google.Protobuf.Reflection new FieldDescriptor(field, file, this, index)); file.DescriptorPool.AddSymbol(this); } + + /// <summary> + /// Returns the total number of nested types and enums, recursively. + /// </summary> + private int CountTotalGeneratedTypes() + { + return nestedTypes.Sum(nested => nested.CountTotalGeneratedTypes()) + enumTypes.Count; + } /// <summary> /// The brief name of the descriptor's target. @@ -94,6 +108,11 @@ namespace Google.Protobuf.Reflection internal DescriptorProto Proto { get { return proto; } } /// <summary> + /// The generated type for this message, or <c>null</c> if the descriptor does not represent a generated type. + /// </summary> + public Type GeneratedType { get { return generatedType; } } + + /// <summary> /// Returns whether this message is one of the "well known types" which may have runtime/protoc support. /// </summary> internal bool IsWellKnownType @@ -142,6 +161,13 @@ namespace Google.Protobuf.Reflection } /// <summary> + /// Returns a map from field number to accessor. + /// TODO: Revisit this. It's mostly in place to make the transition from FieldAccessorTable + /// to descriptor-based reflection simple in terms of tests. Work out what we really want. + /// </summary> + public IDictionary<int, IFieldAccessor> FieldAccessorsByFieldNumber { get { return fieldAccessorsByFieldNumber; } } + + /// <summary> /// Finds a field by field name. /// </summary> /// <param name="name">The unqualified name of the field (e.g. "foo").</param> @@ -192,6 +218,8 @@ namespace Google.Protobuf.Reflection { oneof.CrossLink(); } + + fieldAccessorsByFieldNumber = new ReadOnlyDictionary<int, IFieldAccessor>(fields.ToDictionary(field => field.FieldNumber, field => field.Accessor)); } } }
\ No newline at end of file |