issue with protobuf serialization

72 Views Asked by At

I have an untouchable assembly code with few get only properties. I have tried to create the RuntimeTypeModel, but Protobuf cannot serialize readonly properties of the assembly.

Details: I cannot make modification to the LogEntry class provide by Microsoft assembly (Microsoft.Practices.EnterpriseLibrary.Logging). But I have a requirement to serialize it and its derived classes to ProtoBuf.

Please let me know if there is any solution for the same ?

Thanks in advance!

Code Snippet:

            var model = RuntimeTypeModel.Create();
            AddTypeToModel<LogEntry>(model).AddSubType(100, typeof(LogItem))
                .AddSubType(200, typeof(GenericEventLogEntry));

            AddTypeToModel<LogItem>(model);
            AddTypeToModel<GenericEventLogEntry>(model);

            model.Serialize(iStream, object);


    private static MetaType AddTypeToModel<T>(RuntimeTypeModel typeModel)
    {
        var properties = typeof(T)
            .GetProperties()
            .Where(p => p.GetCustomAttributes<ProtoIncludeAttribute>(true).Any())   // Trial 1
            //.Where(p => p.CanWrite)                                               // Trial 2
            .Select(p => p.Name)
            .OrderBy(name => name);
        return typeModel.Add(typeof(T), true).Add(properties.ToArray());
    }

Please Note: I cannot add attribues [ProtoContract], [ProtoIgnore] or [ProtoMember] to the LogEntry class as it recide in an assembly provided by Microsoft.

1

There are 1 best solutions below

1
jpa On

I cannot add attribues [ProtoContract], [ProtoIgnore] or [ProtoMember] to the LogEntry class as it recide in an assembly provided by Microsoft.

Make a new class with the annotations, and copy the data to it before serialization.

[ProtoContract]
class SerializableLogEntry
{
     [ProtoMember(...)]
     public string MachineName { get; set; }

     [ProtoMember(...)]
     public string Message { get; set; }

     public SerializableLogEntry(LogEntry e)
     {
         MachineName = e.MachineName;
         Message = e.Message;
         ...
     }

}

Seems like the simplest solution to me.