public async Task <byte[]> Serialize(string topic, T data, bool isKey) { try { // We need the topic name when creating the if (_writerSchema == null) { _writerSchema = (global::Avro.Schema) typeof(T).GetField("_SCHEMA", BindingFlags.Public | BindingFlags.Static).GetValue(null); _writerSchemaString = _writerSchema.ToString(); _avroWriter = new SpecificWriter <T>(_writerSchema); } await _serializeMutex.WaitAsync().ConfigureAwait(continueOnCapturedContext: false); try { var subject = isKey ? SubjectNameFactory.KeySubjectNameFrom <T>(topic) : SubjectNameFactory.ValueSubjectNameFrom <T>(topic); if (!_subjectsRegistered.Contains(subject)) { // first usage: register/get schema to check compatibility _writerSchemaId = _autoRegisterSchema ? await _schemaRegistryClient.RegisterSchemaAsync(subject, _writerSchemaString).ConfigureAwait(continueOnCapturedContext: false) : await _schemaRegistryClient.GetSchemaIdAsync(subject, _writerSchemaString).ConfigureAwait(continueOnCapturedContext: false); _subjectsRegistered.Add(subject); } } finally { _serializeMutex.Release(); } if (_writerSchemaId.HasValue == false) { throw new Exception("Not SchemaId Available For Message"); } using (var stream = new MemoryStream(_initialBufferSize)) using (var writer = new BinaryWriter(stream)) { stream.WriteByte(ConfluentConstants.MagicByte); writer.Write(IPAddress.HostToNetworkOrder(_writerSchemaId.Value)); _avroWriter.Write(data, new BinaryEncoder(stream)); // TODO: maybe change the ISerializer interface so that this copy isn't necessary. return(stream.ToArray()); } } catch (AggregateException e) { if (e.InnerException == null) { throw; } throw e.InnerException; } }
public SpecificSerializerImpl( ISchemaRegistryClient schemaRegistryClient, bool autoRegisterSchema, int initialBufferSize) { this.schemaRegistryClient = schemaRegistryClient; this.autoRegisterSchema = autoRegisterSchema; this.initialBufferSize = initialBufferSize; Type writerType = typeof(T); if (typeof(ISpecificRecord).IsAssignableFrom(writerType)) { writerSchema = (global::Avro.Schema) typeof(T).GetField("_SCHEMA", BindingFlags.Public | BindingFlags.Static).GetValue(null); } else if (writerType.Equals(typeof(int))) { writerSchema = global::Avro.Schema.Parse("int"); } else if (writerType.Equals(typeof(bool))) { writerSchema = global::Avro.Schema.Parse("boolean"); } else if (writerType.Equals(typeof(double))) { writerSchema = global::Avro.Schema.Parse("double"); } else if (writerType.Equals(typeof(string))) { // Note: It would arguably be better to make this a union with null, to // exactly match the .NET string type, however we don't for consistency // with the Java Avro serializer. writerSchema = global::Avro.Schema.Parse("string"); } else if (writerType.Equals(typeof(float))) { writerSchema = global::Avro.Schema.Parse("float"); } else if (writerType.Equals(typeof(long))) { writerSchema = global::Avro.Schema.Parse("long"); } else if (writerType.Equals(typeof(byte[]))) { // Note: It would arguably be better to make this a union with null, to // exactly match the .NET byte[] type, however we don't for consistency // with the Java Avro serializer. writerSchema = global::Avro.Schema.Parse("bytes"); } else if (writerType.Equals(typeof(Null))) { writerSchema = global::Avro.Schema.Parse("null"); } else { throw new InvalidOperationException( $"AvroSerializer only accepts type parameters of int, bool, double, string, float, " + "long, byte[], instances of ISpecificRecord and subclasses of SpecificFixed." ); } avroWriter = new SpecificWriter <T>(writerSchema); writerSchemaString = writerSchema.ToString(); }