public class UseCase1 // command { public Guid MessageId {get; set;} public string TargetId {get; set;} public int Version {get; set;} public string UseCaseData1 {get; set;} public int UseCaseData2 {get; set;} }
This is actually not a bad way to do it. However, I eventually became annoyed at having the same boilerplate metadata (MessageId, TargetId, Version, for instance) in every message. In grand “I love compiled objects” fashion, I decided it was possible to encapsulate any given message into one segmented contract. Something like this:
public class CommandMessage { public Metadata Meta {get; set;} public ICommand Data {get; set;} } public class Metadata { public Guid MessageId {get; set;} public string TargetId {get; set;} public int Version {get; set;} } public interface ICommand { } public class UseCase1 : ICommand { public string SomeData {get; set;} }
But eventually it hit me that my compiled object obsession was missing one of the biggest advantages of the JSON format. It’s something I first heard on the DDD/CQRS groups called weak serialization. And once you see it, it’s so obvious. So let me boldly state the obvious with code.
public class Metadata { public Guid MessageId {get; set;} public string TargetId {get; set;} public int Version {get; set;} } public class UseCase1 { public string UseCaseData1 {get; set;} public int UseCaseData2 {get; set;} }
{ MessageId: "...", TargetId: "asdf-1", Version: 0, UseCaseData1: "asdf", UseCaseData2: 7 }
var meta = JsonConvert .Deserialize<MetaData>(requestBodyString);
var command = JsonConvert .Deserialize<UseCase1>(requestBodyString);
Lesson: don’t treat the JSON message as an “object”. Treat it as a data container (dictionary) which could represent multiple objects. This also frees me to add arbitrary meta information to any message without affecting other parts of the system… naming conflicts not withstanding.
No comments:
Post a Comment