Run time initialisation of protobuf-net v2 without annotation

Posted on

I have been using protobuf-net for the project at office but it’s only implemented for a limited number of entities (or business objects). We’re now trying to see how to implement this to the whole entities that we’re sending back n forth between the UI and the back end.

As we’re currently using a code generation “tool” to produce the code, we’re thinking to incorporate the annotation/attribute into the generated class/property code, however due to some not really technical reason, this is a bit complicated to achieve.

I thought of checking the site again to get some idea and I came across to this statement “allow use without attributes if you wish” on the page.

Then I tried to dig out more on the SO and found some more good leads on this. Apparently it’s very much possible to perform “registration” during run time mode which allows us NOT to use any annotation on the entities.

So thanks to the pointers, there are 2 alternatives for this:
1. With very minimal annotation on the class level

[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)] // only required on the class level
class PersonEntity
   public string FirstName { get; set; }
   public string LastName { get; set; }

2. Without any annotation (using RuntimeTypeModel)

static void InitializeProtobufRunTime()
    var assembly = Assembly.GetAssembly(typeof(PlainEntities.PersonEntity));
    var types = assembly.GetTypes();
    foreach (var t in types.Where(x => x.Namespace.Contains("PlainEntities")))
        Console.WriteLine("Processing {0}", t.FullName);
        var meta = RuntimeTypeModel.Default.Add(t, false);
        var index = 1;

        // find any derived class for the entity
        foreach (var d in types.Where(x => x.IsSubclassOf(t)))
            var i = index++;
            Console.WriteLine("\tSubtype: {0} - #{1}", d.Name, i);
            meta.AddSubType(i, d);

        // then add the properties
        foreach (var p in t.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly).Where(x => x.GetSetMethod() != null))
            var i = index++;
            Console.WriteLine("\tProperty: {0} - #{1}", p.Name, i);
            meta.AddField(i, p.Name);

And both the above works quite well without any performance differences.

Process: 100000 items, MemorySize: 7400705, Completed in: 3877 ms, Serialization took: 676 ms, Deserialization took: 2948 ms

Process: 100000 items, MemorySize: 3983490, Completed in: 682 ms, Serialization took: 164 ms, Deserialization took: 253 ms

Process: 100000 items, MemorySize: 3983490, Completed in: 595 ms, Serialization took: 104 ms, Deserialization took: 210 ms

Processing ProtobufTestConsole.PlainEntities.BaseEntity
Subtype: PersonEntity - #1
Property: Id - #2
Property: Gender - #3
Processing ProtobufTestConsole.PlainEntities.PersonEntity
Property: FirstName - #1
Property: LastName - #2
Property: Age - #3
Process: 100000 items, MemorySize: 4083490, Completed in: 646 ms, Serialization took: 113 ms, Deserialization took: 232 ms

Looking forward to get this in :)

Also attached the sample project for reference

Sample Project

3 thoughts on “Run time initialisation of protobuf-net v2 without annotation

    […] This is a continuation from my previous post of Run time initialisation of protobuf-net v2 without annotation […]

    dave said:
    June 9, 2015 at 8:10 pm

    It would be nice if you put the solution up on github. Some of us in the enterprise world have restrictions on accessing google drive.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s