/// <summary>
        /// Serialize a message. (See <see cref="IAsyncSerializer{T}.SerializeAsync(T, SerializationContext)" />.)
        /// </summary>
        public virtual async Task <byte[]> SerializeAsync(T data, SerializationContext context)
        {
            var serialize = await(_cache.GetOrAdd(_subjectNameBuilder(context), async subject =>
            {
                int id;
                Action <T, Stream> @delegate;

                try
                {
                    var existing = await _resolve(subject).ConfigureAwait(false);
                    var schema   = _schemaReader.Read(existing.SchemaString);

                    @delegate = _serializerBuilder.BuildDelegate <T>(schema);
                    id        = existing.Id;
                }
                catch (Exception e) when(_registerAutomatically && (
                                             (e is SchemaRegistryException sre && sre.ErrorCode == 40401) ||
                                             (e is UnsupportedTypeException)
                                             ))
                {
                    var schema = _schemaBuilder.BuildSchema <T>();
                    var json   = _schemaWriter.Write(schema);

                    @delegate = _serializerBuilder.BuildDelegate <T>(schema);
                    id        = await _register(subject, json).ConfigureAwait(false);
                }

                var bytes = BitConverter.GetBytes(id);

                if (BitConverter.IsLittleEndian)
                {
                    Array.Reverse(bytes);
                }

                return(value =>
                {
                    var stream = new MemoryStream();

                    using (stream)
                    {
                        stream.WriteByte(0x00);
                        stream.Write(bytes, 0, bytes.Length);

                        @delegate(value, stream);
                    }

                    return stream.ToArray();
                });
            })).ConfigureAwait(false);

            return(serialize(data));
        }
        /// <summary>
        /// Builds a serializer for a specific schema.
        /// </summary>
        /// <param name="subject">
        /// The subject of the schema that should be used to serialize data. The latest version of
        /// the subject will be resolved.
        /// </param>
        /// <param name="registerAutomatically">
        /// Whether to automatically register a schema that matches <typeparamref name="T" /> if
        /// one does not already exist.
        /// </param>
        /// <exception cref="UnsupportedTypeException">
        /// Thrown when the type is incompatible with the retrieved schema or a matching schema
        /// cannot be generated.
        /// </exception>
        public async Task <ISerializer <T> > Build <T>(string subject, bool registerAutomatically = false)
        {
            try
            {
                var schema = await RegistryClient.GetLatestSchemaAsync(subject);

                return(Build <T>(schema.Id, schema.SchemaString));
            }
            catch (Exception e) when(registerAutomatically && (
                                         (e is SchemaRegistryException sre && sre.ErrorCode == 40401) ||
                                         (e is UnsupportedTypeException)
                                         ))
            {
                var schema = _schemaBuilder.BuildSchema <T>();
                var json   = _schemaWriter.Write(schema);

                var id = await RegistryClient.RegisterSchemaAsync(subject, json);

                return(Build <T>(id, json));
            }
        }