diff options
Diffstat (limited to 'csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs')
-rw-r--r-- | csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs | 68 |
1 files changed, 50 insertions, 18 deletions
diff --git a/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs index 1c22c460..b29b4b20 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,31 +62,47 @@ 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, GeneratedCodeInfo generatedCodeInfo) : base(file, file.ComputeFullName(parent, proto.Name), typeIndex) { this.proto = proto; - containingType = parent; - - oneofs = DescriptorUtil.ConvertAndMakeReadOnly(proto.OneofDecl, - (oneof, index) => - new OneofDescriptor(oneof, file, this, index)); + generatedType = generatedCodeInfo == null ? null : generatedCodeInfo.ClrType; - nestedTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.NestedType, - (type, index) => - new MessageDescriptor(type, file, this, index)); - - enumTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.EnumType, - (type, index) => - new EnumDescriptor(type, file, this, index)); + containingType = parent; - // TODO(jonskeet): Sort fields first? - fields = DescriptorUtil.ConvertAndMakeReadOnly(proto.Field, - (field, index) => - new FieldDescriptor(field, file, this, index)); + oneofs = DescriptorUtil.ConvertAndMakeReadOnly( + proto.OneofDecl, + (oneof, index) => + new OneofDescriptor(oneof, file, this, index, generatedCodeInfo == null ? null : generatedCodeInfo.OneofNames[index])); + + nestedTypes = DescriptorUtil.ConvertAndMakeReadOnly( + proto.NestedType, + (type, index) => + new MessageDescriptor(type, file, this, index, generatedCodeInfo == null ? null : generatedCodeInfo.NestedTypes[index])); + + enumTypes = DescriptorUtil.ConvertAndMakeReadOnly( + proto.EnumType, + (type, index) => + new EnumDescriptor(type, file, this, index, generatedCodeInfo == null ? null : generatedCodeInfo.NestedEnums[index])); + + fields = DescriptorUtil.ConvertAndMakeReadOnly( + proto.Field, + (field, index) => + new FieldDescriptor(field, file, this, index, generatedCodeInfo == null ? null : generatedCodeInfo.PropertyNames[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 +112,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 +165,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 +222,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 |