Question

I have the EF databaseModel. I serialize my class thet contains field with EF DB Table Type. I try to deserealize and i have the field with null fields.

class Myclass
{
    public EFTable table {get;set;}
}

EFTable

  • string str;
  • int num;

[global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)] [global::System.Runtime.Serialization.DataMemberAttribute()] [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")]

After deserialization EFTable - string str=null - int num=0

why? how fix it without creating temp classes?

public static byte[] Serialize(BaseInspection inspection)
{
    using (var file = File.Create(path.ToString()))
    {
        Serializer.Serialize(file, inspection);
    }
    return File.ReadAllBytes(path.ToString());
}

static BaseInspection Desirialize(byte[] path)
{

    using (Stream stream = new MemoryStream(path))
        return Serializer.Deserialize<BaseInspection>(stream);           
}
Was it helpful?

Solution

If you can't specify attributes under your model, you can go with second approach to fill RuntimeTypeModel at application start. Here is a sample given my Marc Gravell - Protobuf-net serialization without annotation

Code sample for your EFTable:

RuntimeTypeModel.Default.Add(typeof(EFTable), false).Add("str", "num",);

Or you can fill it with reflection based on your EFTable properties, and then it should serialize correctly.

But beware, as Protobuf is critical to properties order. And if you fill this RuntimeTypeModel object dynamically by reflection, and then you will add new property, then data that was serialized with previous version, won`t work in new version, as properties order will be changed.

UPDATE1

As I mentioned you can also use reflection to populate fields dynamically. Here is a sample of such method:

public static void Generate(IEnumerable<Type> types)
{
    var model = RuntimeTypeModel.Default;

    foreach (var type in types)
    {
        int counter = 1;
        var metaType = model.Add(type, false);

        var properties = type.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);
        foreach (var propertyInfo in properties)
        {
            metaType.Add(counter++, propertyInfo.Name);
        }

    }
}   

And usage sample:

Generate(new List<Type>() { // list of objects that should be registered with ProtoBuf-Net
    typeof(ASPStateTempSession),  
    typeof(ASPStateTempApplication) 
});

But as i previously said, if you add new property in new version of your application, then old saved cached data won't work, as order of properties will be changed.

OTHER TIPS

If the classes are being generated, it is very likely they are being generated as partial classes. In which case, you can add the attributes separately in a separate code file:

namespace YourNamespace
{
    [ProtoContract]
    [ProtoPartialMember(1, "table")]
    partial class Myclass {}
}

This will be merged at compile-time, and protobuf-net knows to look for the ProtoPartialMember alternative form.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top