Skip to content

Instantly share code, notes, and snippets.

@Horusiath
Created September 27, 2017 06:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Horusiath/8287121117dd739495800958f79b5aee to your computer and use it in GitHub Desktop.
Save Horusiath/8287121117dd739495800958f79b5aee to your computer and use it in GitHub Desktop.
Generic Google Protocol Buffers serializer for Akka.NET
using System;
using Akka.Actor;
using Akka.Configuration;
using Akka.Serialization.Protobuf;
using ProtoBuf;
namespace App
{
/// <summary>
/// Interface used to recognize messages to be serialized by <see cref="ProtobufSerializer"/>.
/// </summary>
public interface IProto { }
[ProtoContract]
public sealed class TestMessage : IProto
{
[ProtoMember(1)]
public int Id { get; }
[ProtoMember(2)]
public string Body { get; }
// Protobuf-net requires class to provide parameterless constructor
// however it may be private.
private TestMessage() { }
public TestMessage(int id, string body)
{
Id = id;
Body = body;
}
}
class Program
{
static void Main(string[] args)
{
// configure serializer via HOCON
var config = ConfigurationFactory.ParseString(@"
akka.actor {
serializers.protobuf = ""Akka.Serialization.Protobuf.ProtobufSerializer, Akka.Serialization.Protobuf""
serialization-bindings {
""App.IProto, App"" = protobuf
}
}");
using (var system = ActorSystem.Create("system", config))
{
var msg = new TestMessage(123, "Hello world!");
var serializer = system.Serialization.FindSerializerForType(msg.GetType());
var bin = serializer.ToBinary(msg);
var des = serializer.FromBinary(bin, typeof(TestMessage));
}
}
}
}
using System;
using System.IO;
using Akka.Actor;
namespace Akka.Serialization.Protobuf
{
/// <summary>
/// Generic Google Protocol Buffers serializer for Akka.NET using Marc Gravell protobuf-net.
/// </summary>
public sealed class ProtobufSerializer : Serializer
{
public ProtobufSerializer(ExtendedActorSystem system) : base(system)
{
}
public override byte[] ToBinary(object obj)
{
using (var stream = new MemoryStream())
{
ProtoBuf.Serializer.Serialize(stream, obj);
return stream.ToArray();
}
}
public override object FromBinary(byte[] bytes, Type type)
{
using (var stream = new MemoryStream(bytes))
{
return ProtoBuf.Serializer.Deserialize(type, stream);
}
}
public override bool IncludeManifest => false;
public override int Identifier => 127;
}
}
@beachwalker
Copy link

beachwalker commented Apr 17, 2022

How would this work together with .proto files? Their generated types have no common interface afaik.

@Horusiath
Copy link
Author

@beachwalker this approach uses Marc Gravell's Protobuf library which - at least at the moment of writing that snippet - was not using .proto files. Re. generated types - in almost all cases they use partial classes, which gives you an opportunity to extend them with empty interface that can be used for serializer binding.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment