繁体   English   中英

扩展其GetObjectData方法未标记为虚拟的类时的序列化

[英]Serialization when extending a class whose GetObjectData method is not marked virtual

我正在尝试扩展一个框架。 我正在扩展的其中一个类是序列化的。 基类' GetObjectData()方法未标记为虚拟,因此我无法覆盖它。

现在,如果对象在被引用为基类时被序列化,则它不是多态的,因此只调用基类' GetObjectData

有没有办法解决这个问题而不修改基类' GetObjectData以将其标记为虚拟?

[编辑]我扩展了类并添加了一个我要序列化的属性。 以下问题的简单示例

[Serializable]
public class ParentClass : ISerializable 
{

    public float m_parent = 1.73f;

    public ParentClass() 
    { }

    public ParentClass(SerializationInfo info, StreamingContext context)
    {
        Debug.Log("Loading parent");
        m_parent = (float)info.GetValue("m_parent", typeof(float));
    }

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        Debug.Log("Saving parent");
        info.AddValue("m_parent", m_parent, typeof(float));
    }
}


[Serializable]
public class ChildClass : ParentClass
{
    public int m_child = 73;

    public ChildClass()
    { }

    public ChildClass(SerializationInfo info, StreamingContext context) : base(info, context)
    {
        Debug.Log("Loading child");
        m_child = (int)info.GetValue("m_child", typeof(int));
    }

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        Debug.Log("Saving child");
        info.AddValue("m_child", m_child, typeof(int));
        base.GetObjectData(info, context);
    }
}

void Save()
{
    Debug.Log("Starting save");
    ParentClass aParent = new ChildClass() as ParentClass;
    using (Stream stream = File.Open(fileName, FileMode.Create))
    {
        BinaryFormatter bFormatter = new BinaryFormatter();
        bFormatter.Serialize(stream, aParent);
    }
    Debug.Log("Save complete");
}

void Load()
{
    Debug.Log("Starting load");
    ChildClass aChild;
    using (Stream stream = File.Open(fileName, FileMode.Open))
    {
        BinaryFormatter bFormatter = new BinaryFormatter();
        aChild = bFormatter.Deserialize(stream) as ChildClass;
    }
    Debug.Log("Load complete" + aChild.m_child);
}

执行保存/加载会产生以下错误:

SerializationException: No element named m_child could be found.

你需要做两件事:

  1. ChildClass明确标记为ISerializable

  2. 如Will所暗,使用子类中的new修饰符声明一个GetObjectData

    要么

    在子类中显式实现接口。

例如:

[Serializable]
public class ChildClass : ParentClass, ISerializable
{
    public int m_child = 73;

    public ChildClass()
    { }

    public ChildClass(SerializationInfo info, StreamingContext context)
        : base(info, context)
    {
        Debug.WriteLine("Loading child");
        m_child = (int)info.GetValue("m_child", typeof(int));
    }

    public new void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        Debug.WriteLine("Saving child");
        info.AddValue("m_child", m_child, typeof(int));
        base.GetObjectData(info, context);
    }
}

由于BinaryFormatter.Serialize(Stream, Object)是非泛型的,因此将发现并使用派生最多的接口实现。

有关其工作原理的详细信息,请参阅c#语言规范第13.4.4节接口重新实现

允许继承接口实现的类通过将其包含在基类列表中来重新实现接口。

在不确切知道需要GetObjectData的情况下,您可以使用一些自定义方法在序列化/反序列化期间操作对象:

[Serializable]
public MySerializableClass : MyUnforgivingBaseClass
{
    [OnSerializing]
    public void OnSerializing(StreamingContext context)
    {
         //You can modify the object before serialization here
    }

    [OnDeserializing]
    public void OnDeserializing(StreamingContext context)
    {
        //You can modify the object during deserialization here
    }
}

请参阅https://msdn.microsoft.com/en-us/library/system.runtime.serialization.ondeserializingattribute(v=vs.110).aspxhttps://msdn.microsoft.com/en-us/library/ system.runtime.serialization.onserializingattribute%28V = vs.110%29.aspx

您可以使用new修饰符覆盖基类的实现。


如果序列化程序由基类引用它,这将无济于事。 它必须被引用为new重写才能工作的子类型。

在这种情况下,你唯一的希望是1)替换序列化逻辑,以便你可以控制它,2)使用代理类进行序列化,来回映射到框架类,3)分叉框架来修复它的局限性或4)魔术

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM