Reputation: 31
Is there a possibility to serialize classes, that contain non-serializable members?
Example: I have a class Instruction, which has two members:
public class Instruction
{
public OpCode Op { get; set; }
public object Operand { get; set; }
}
The problem is, that the type of the member Op is in a 3rd party library and I can't make it serializable. I tried BinaryFormatter and ProtoBuf, but both failed without marking the Op-member.
Anyone knows a solution to serialize my object anyway?
Upvotes: 3
Views: 2810
Reputation: 111840
You could:
public class Instruction
{
public OpCode Op { get; set; }
public string OpString
{
get
{
return Op.Name;
}
set
{
Op = (OpCode)typeof(OpCodes).GetField(value, BindingFlags.Static | BindingFlags.Public | BindingFlags.IgnoreCase).GetValue(null);
}
}
public object Operand { get; set; }
}
and disable serialization for Op
. In this way you would serialize the Name
of the op code (a string
), and you would then be able to deserialize it.
With BinaryFormatter
you could use the ISerializable
interface and manually serialize:
[Serializable]
public class Instruction : ISerializable
{
public OpCode Op { get; set; }
public object Operand { get; set; }
public Instruction()
{
}
public Instruction(SerializationInfo info, StreamingContext context)
{
Op = (OpCode)typeof(OpCodes).GetField(info.GetString("Op"), BindingFlags.Static | BindingFlags.Public | BindingFlags.IgnoreCase).GetValue(null);
Operand = info.GetValue("Operand", typeof(object));
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Op", Op.Name);
info.AddValue("Operand", Operand);
}
}
Example of use:
var ins1 = new Instruction { Op = OpCodes.Add, Operand = (short)5 };
var ins2 = new Instruction { Op = OpCodes.Sub, Operand = 5.0 };
byte[] bytes;
using (var ms = new MemoryStream())
{
var bf = new BinaryFormatter();
bf.Serialize(ms, ins1);
bf.Serialize(ms, ins2);
bytes = ms.ToArray();
}
Instruction ins3, ins4;
using (var ms = new MemoryStream(bytes))
{
var bf = new BinaryFormatter();
ins3 = (Instruction)bf.Deserialize(ms);
ins4 = (Instruction)bf.Deserialize(ms);
}
If Operand
can be something that isn't directly serializable, you can then create a surrogate of it inside the the GetObjectData
.
Upvotes: 2
Reputation: 116
One way is to create a wrapper class over Opcode and use object of this wrapper class in Instruction class for serialisation and other purposes in your application. In this way, you can get rid of any limitations with third party library.
Upvotes: 2
Reputation: 5550
Obviously if a part of a class is not serializable, you can't serialize that part, but you can ignore it (and give some default, probably null
value when deserializing).
You can use the [ProtoIgnore]
attribute to mark the Op
property if you are using ProtoBuf
, or the [NonSerialized]
attributes for BinaryFormatter
.
Upvotes: 3