序列化包含非可序列化成员的类

3

有没有可能序列化包含非序列化成员的类?

例如: 我有一个类Instruction,它有两个成员:

public class Instruction
{
    public OpCode Op { get; set; }
    public object Operand { get; set; } 
}

问题在于,成员Op的类型属于第三方库,我无法将其序列化。我尝试过BinaryFormatter和ProtoBuf,但是都无法在不标记Op成员的情况下成功。

有人知道如何在这种情况下对我的对象进行序列化吗?

3个回答

3

显然,如果类的某个部分不可序列化,则无法对该部分进行序列化,但可以忽略它(并在反序列化时提供一些默认值,可能是null)。

如果您使用ProtoBuf,则可以使用[ProtoIgnore]属性标记Op属性,或使用[NonSerialized]属性来标记BinaryFormatter


但是如果我需要稍后使用该成员怎么办? - user4653488
你不能序列化一个不可序列化的对象。如果没有反向工程类并查看如何强制序列化,你就无能为力了。也许 OpCode 正在使用本地资源? - Mark Segal

2

您可以:

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; }
}

禁用Op的序列化。这样,您将序列化op代码的Name(一个string),然后可以进行反序列化。

使用BinaryFormatter时,您可以使用ISerializable接口并手动序列化:

[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);
    }
}

使用实例:

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);
}

如果Operand是一些不能直接序列化的东西,那么你可以在GetObjectData内创建它的替代品。

这是 OpCode 的可能方法,但对于对象来说不起作用,对吧?我的意思是,操作数可以拥有多种类型。 - user4653488
@user 请查看详细回复。遗憾的是,protobuf不支持在“object”内序列化基本类型(intshort,...)。 - xanatos

2

一种方法是创建一个Opcode的包装类,然后在指令类中使用该包装类的对象进行序列化和其他应用。通过这种方式,您可以摆脱第三方库的任何限制。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接