-
Notifications
You must be signed in to change notification settings - Fork 87
Description
Hi all,
I have bee working in event-driven architectures using RabbitMQ for the last years, and the approach, for relatively small products, is that the project that owns an event is declaring the event in a separate project like (oversimplifying):
public record MyEvent(string topic, ..., MyPayload payload) : BaseEvent { ... }
A library receives the instance and serializes it all to publish it to RabbitMQ. And on the subscribing side, it uses the class definition to deserialize the string and pass it onto the subscription.
This allows all actors (publishers, subscribers, tests, etc) to use a single definition for a single event while freeing all the code from serialization, deserialization and casting.
I am looking to migrate this implementation to CloudEvents, so the first thing I thought about was:
public record BaseEvent<T> : CloudEvent
{
// constructor...
// json attribute
public TPayload Payload {get:}
}
But CloudEvent
is sealed :(
My first alternative is to declare my BaseEvent with operators to cast to and from CloudEvent
:
using CloudNative.CloudEvents;
using System.Text.Json;
public abstract record BaseEvent<TPayload>
{
public string Id { get; init; } = Guid.NewGuid().ToString();
public string Type { get; init; }
public Uri Source { get; init; }
public string Subject { get; init; }
public DateTimeOffset Time { get; init; } = DateTimeOffset.UtcNow;
public TPayload Data { get; init; }
protected BaseEvent(TPayload data, string source, string type, string subject = null)
{
Data = data;
Source = new Uri(source);
Type = type;
Subject = subject;
}
public static implicit operator CloudEvent(BaseEvent<TPayload> baseEvent)
{
return new CloudEvent
{
Id = baseEvent.Id,
Type = baseEvent.Type,
Source = baseEvent.Source,
Subject = baseEvent.Subject,
Time = baseEvent.Time,
Data = JsonSerializer.Serialize(baseEvent.Data),
DataContentType = "application/json"
};
}
public static implicit operator BaseEvent<TPayload>(CloudEvent cloudEvent)
{
var data = JsonSerializer.Deserialize<TPayload>(cloudEvent.Data.ToString());
var baseEvent = Activator.CreateInstance(typeof(BaseEvent<TPayload>), data, cloudEvent.Source.ToString(), cloudEvent.Type, cloudEvent.Subject) as BaseEvent<TPayload>;
baseEvent.Id = cloudEvent.Id;
baseEvent.Time = cloudEvent.Time.Value;
return baseEvent;
}
}
But before I move forward, I am double checking:
- What would be the proposed way to declare cloud events strongly typed?
An additionally:
- Why is
CloudEvent
sealed? - Why is it a class and not a record?
Thanks