I'm using protobuf-net (version 2.0.0.621) and having a problem serializing List type where T is my own class (it does't matter what it contains) and a surrogate is set for T.
The surrogate is set like this:
ProtoBuf.Meta.RuntimeTypeModel.Default.Add(typeof(MyClass), false).SetSurrogate(typeof(MyClassSurrogate));
MyClass:
public class MyClass
{
public int Number { get; set; }
}
[ProtoContract]
MyClassSurrogate
{
[ProtoMember(1)]
public int Number { get; set; }
}
Then I create a generic list of type MyClass instance, fill it with items and serialize it like this:
ProtoBuf.Serializer.Serialize(stream, list);
The problem occurs on deserialization, I keep getting "null" in the surrogate in the implicit operator conversion:
static public implicit operator MyClassSurrogate(MyClass myClass)
then 'myClass' is null.
If I remove the surrogate and decorate MyClass with the proto attributes, everything works fine.
Can you tell me what I'm doing wrong?
Thanks.
Adding a null check to the implicit operator conversion seems to fix the issue, i.e:
public static implicit operator MyClassSurrogate(MyClass myClass)
{
return myClass != null ? new MyClassSurrogate { Number = myClass.Number } : null;
}
The implicit operator is initially called once with a null value on deserialization with the result appearing to be ignored.
Full implementation of MyClassSurrogate:
[ProtoContract]
public class MyClassSurrogate
{
[ProtoMember(1)]
public int Number { get; set; }
public static implicit operator MyClassSurrogate(MyClass myClass)
{
return
myClass != null
? new MyClassSurrogate { Number = myClass.Number }
: null;
}
public static implicit operator MyClass(MyClassSurrogate myClass)
{
return new MyClass { Number = myClass.Number };
}
}
Full Serialization/Deserialization example:
var model = ProtoBuf.Meta.RuntimeTypeModel.Default;
model.Add(typeof(MyClassSurrogate), true);
model.Add(typeof(MyClass), false).SetSurrogate(typeof(MyClassSurrogate));
var stream = new System.IO.MemoryStream();
var list = new List<MyClass>();
for (int x = 0; x < 10; x++) list.Add(new MyClass { Number = x });
ProtoBuf.Serializer.Serialize(stream, list);
stream.Seek(0, SeekOrigin.Begin);
var xs = ProtoBuf.Serializer.Deserialize<List<MyClass>>(stream);
foreach (var x in xs) Debug.WriteLine(x.Number);
The value null is used pretty often, including during deserialization. You should be able to fix this simply by telling the conversion operator to translate null as null:
if(value == null) return null;
Thinking about it, I can probably safely add a "if both are reference types, translate null as null automatically".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With