/// <summary> /// Look up and cross-link all field types etc. /// </summary> internal void CrossLink() { if (Proto.HasTypeName) { IDescriptor typeDescriptor = File.DescriptorPool.LookupSymbol(Proto.TypeName, this); if (Proto.HasType) { // Choose field type based on symbol. if (typeDescriptor is MessageDescriptor) { fieldType = FieldType.Message; } else if (typeDescriptor is EnumDescriptor) { fieldType = FieldType.Enum; } else { throw new DescriptorValidationException(this, $"\"{Proto.TypeName}\" is not a type."); } } if (fieldType == FieldType.Message || fieldType == FieldType.Group) { if (!(typeDescriptor is MessageDescriptor)) { throw new DescriptorValidationException(this, $"\"{Proto.TypeName}\" is not a message type."); } messageType = (MessageDescriptor)typeDescriptor; if (Proto.HasDefaultValue) { throw new DescriptorValidationException(this, "Messages can't have default values."); } } else if (fieldType == FieldType.Enum) { if (!(typeDescriptor is EnumDescriptor)) { throw new DescriptorValidationException(this, $"\"{Proto.TypeName}\" is not an enum type."); } enumType = (EnumDescriptor)typeDescriptor; } else { throw new DescriptorValidationException(this, "Field with primitive type has type_name."); } } else { if (fieldType == FieldType.Message || fieldType == FieldType.Enum) { throw new DescriptorValidationException(this, "Field with message or enum type missing type_name."); } } if (Proto.HasExtendee) { extendeeType = File.DescriptorPool.LookupSymbol(Proto.Extendee, this) as MessageDescriptor; } // Note: no attempt to perform any default value parsing File.DescriptorPool.AddFieldByNumber(this); if (ContainingType != null && ContainingType.Proto.Options != null && ContainingType.Proto.Options.MessageSetWireFormat) { throw new DescriptorValidationException(this, "MessageSet format is not supported."); } accessor = CreateAccessor(); }