using System.Collections.Generic; using Google.ProtocolBuffers.DescriptorProtos; namespace Google.ProtocolBuffers.Descriptors { /// /// Describes a message type. /// public class MessageDescriptor : IndexedDescriptorBase { private readonly MessageDescriptor containingType; private readonly IList nestedTypes; private readonly IList enumTypes; private readonly IList fields; private readonly IList extensions; internal MessageDescriptor(DescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int typeIndex) : base(proto, file, ComputeFullName(file, parent, proto.Name), typeIndex) { containingType = parent; nestedTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.NestedTypeList, (type, index) => new MessageDescriptor(type, file, this, index)); enumTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.EnumTypeList, (type, index) => new EnumDescriptor(type, file, this, index)); fields = DescriptorUtil.ConvertAndMakeReadOnly(proto.FieldList, (field, index) => new FieldDescriptor(field, file, this, index, false)); extensions = DescriptorUtil.ConvertAndMakeReadOnly(proto.ExtensionList, (field, index) => new FieldDescriptor(field, file, this, index, true)); file.DescriptorPool.AddSymbol(this); } /// /// If this is a nested type, get the outer descriptor, otherwise null. /// public MessageDescriptor ContainingType { get { return containingType; } } /// /// An unmodifiable list of this message type's fields. /// public IList Fields { get { return fields; } } /// /// An unmodifiable list of this message type's extensions. /// public IList Extensions { get { return extensions; } } /// /// An unmodifiable list of this message type's nested types. /// public IList NestedTypes { get { return nestedTypes; } } /// /// An unmodifiable list of this message type's enum types. /// public IList EnumTypes { get { return enumTypes; } } /// /// Determines if the given field number is an extension. /// public bool IsExtensionNumber(int number) { foreach (DescriptorProto.Types.ExtensionRange range in Proto.ExtensionRangeList) { if (range.Start <= number && number < range.End) { return true; } } return false; } /// /// Finds a field by field number. /// /// The field number within this message type. /// The field's descriptor, or null if not found. public FieldDescriptor FindFieldByNumber(int number) { return File.DescriptorPool.FindFieldByNumber(this, number); } /// /// Finds a nested descriptor by name. The is valid for fields, nested /// message types and enums. /// /// The unqualified name of the descriptor, e.g. "Foo" /// The descriptor, or null if not found. public T FindDescriptor(string name) where T : class, IDescriptor { return File.DescriptorPool.FindSymbol(FullName + "." + name); } /// /// Looks up and cross-links all fields, nested types, and extensions. /// internal void CrossLink() { foreach (MessageDescriptor message in nestedTypes) { message.CrossLink(); } foreach (FieldDescriptor field in fields) { field.CrossLink(); } foreach (FieldDescriptor extension in extensions) { extension.CrossLink(); } } } }