SteveDunn / Vogen

A semi-opinionated library which is a source generator and a code analyser. It Source generates Value Objects
Apache License 2.0
853 stars 45 forks source link

More (binary) serializers support: protobuf, messagepack #305

Open justmara opened 1 year ago

justmara commented 1 year ago

Describe the feature

These serializers (protobuf-net, messagepack-csharp) are fast binary ones, already stated as industry standards (like, protobuf is used in gRPC) and they require a bit special handling: members decoration with attributes, accessible constructor. These two are pretty hard to be added to models, generated with current version of Vogen. Messagepack can make use of [SerializationConstructor] attribute, for example.

PS: Or is it possible to deal with these using current Vogen version and I (maybe) missed some guide for it?

SteveDunn commented 1 year ago

Hi - thanks for the feature suggestion. I think it'd make an excellent suggestion!

I'm not very familiar with this stuff though, so I'll do a bit of research and add them - hopefully within a week or so.

Thanks again!

justmara commented 1 year ago

I've dug a bit into it and looks like MessagePack formatter is very simple:

public class SkuIdMessagePackFormatter : IMessagePackFormatter<SkuId>
{
    public void Serialize(ref MessagePackWriter writer, SkuId value, MessagePackSerializerOptions options) => writer.WriteInt64(value.Value);

    public SkuId Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
    {
        if (reader.TryReadNil()) return SkuId.Unspecified; // this must be some more general for sure :)

        options.Security.DepthStep(ref reader);

        var value = reader.ReadInt64();

        reader.Depth--;
        return SkuId.From(value);
    }
}

But the protobuf one seems to be pointless overall - it will require adding this type to proto, protobuf-gen wont recognize that special type anyway... Looks like this conversion must be done manually/on mapping stage and does not require any special handling, so can be avoided :)

justmara commented 1 year ago

Also there is very interesting MemoryPack that I wanted to try out, but it uses its own roslyn generator and it fails even building project where it and vogen are added at the same time :(

SteveDunn commented 1 year ago

Interesting! Many thanks, I'll take a look at those.

DomasM commented 11 months ago

protobuf-net can be used with Vogen types very easily if adding dependency to protobuf-net is OK, but this information is not easy to find imho. I guess it's possible to set surrogate for every required type at the runtime too, but this seems more convenient for my use case.

[ValueObject(typeof(string))]
[ProtoContract(Surrogate = typeof(string))]
public partial class BoxId {
//...
}

BoxId type now will be serialized as a string in all messages/grpc calls. If one is generating .proto files for other applications from C# code, proto files will include Surrogate type as the type. @SteveDunn maybe this information should be included in readme?

SteveDunn commented 11 months ago

protobuf-net can be used with Vogen types very easily if adding dependency to protobuf-net is OK, but this information is not easy to find imho. I guess it's possible to set surrogate for every required type at the runtime too, but this seems more convenient for my use case.

[ValueObject(typeof(string))]
[ProtoContract(Surrogate = typeof(string))]
public partial class BoxId {
//...
}

BoxId type now will be serialized as a string in all messages/grpc calls. If one is generating .proto files for other applications from C# code, proto files will include Surrogate type as the type. @SteveDunn maybe this information should be included in readme?

Many thanks for the feedback @DomasM ! I'll certainly add that to the readme!