【问题标题】:Cloning/serialization produces wrong class because of different dlls由于不同的 dll,克隆/序列化会产生错误的类
【发布时间】:2012-05-31 13:52:45
【问题描述】:

我有一个 dll 库 TaskLibrary.dll,其中一个类 Execution 执行一些 Operation(s) 和一个类 ParallelizeExecution,它采用单个 Execution,克隆它并执行 Run 方法多个Execution 实例。

Execution 类的 Clone 方法通过在 xml 中转换 Execution 并将其恢复为正常的新实例来工作

public Execution{
    List<AOperation> operations;

    public Run(){
        foreach(var op in operations){
            //...do stuff...
        }
    }

    public Execution Clone(){
        MyXmlSerializer.DeserializeObject<Execution>(
                MyXmlSerializer.SerializeObject(this));
    }
}

public ParallelizeExecution{
    List<Execution> toRun;
    public RunParallel(Execution e,int numExecutions){
        toRun=new List<Execution>();

        for(var i=0;i<numExecutions;i++){
            toRun.Add(e.Clone());
        }
    }
}

Execution 类是可序列化的,每个实现Operation 的类也是如此。这是通过使用所有IOperation 实现扩展的抽象类(AOperation) 获得的,使用XmlInclude 注释使MyXmlSerializer 为每个IOperation 工作。

[XmlInclude(typeof(Operation1))]
[XmlInclude(typeof(Operation2))]
public abstract class AOperation:IOperation{
    ...
}

现在我有一个引用 TaskLibrary.dll 的新项目。我需要向Execution 添加一种新的操作:

public class Operation3: Operation2 {
}

单次执行一切正常,但是当我使用ParallelizeExecution 时,Operation3 被正确序列化为Operation2,因此执行了不需要的Run 方法。如何将新类型的AOperation 添加到Execution 类并期望它被正确序列化并在Execution 中运行?

如何在不改变Execution 类的序列化方式的情况下避免该问题?

警告:我知道可以使用反射来对任何扩展给定的提示进行 xmlserialize,但我宁愿学习如何使用标准 OOP(如果可能)来做到这一点。

编辑:我可以修改TaskLibrary.dll,但我宁愿避免这种方法,它会浪费我学习新事物和帮助社区的努力,而且重新分配会很痛苦图书馆给那些已经在使用它的人。

【问题讨论】:

    标签: c# generics xml-serialization


    【解决方案1】:

    您可以对XmlSerializer constructor 使用extraTypes 参数。使用反射查找所有相关类型,并使用完整列表创建 XmlSerializer。整体流程布局here,但为后人着想:

    // use reflection to get all derived types
    List<type> knownTypes = new List<type>();
    
    // Iterate over whichever assembly has your types.
    foreach(Type t in Assembly.GetExecutingAssembly().GetTypes())
        if (typeof(Car).IsAssignableFrom(t) || 
            typeof(Wheel).IsAssignableFrom(t) ||
            typeof(Door).IsAssignableFrom(t))
           knownTypes.Add(t);
    
    // prepare to serialize a car object
    XmlSerializer serializer = new XmlSerializer(typeof(Car), knownTypes.ToArray());
    

    【讨论】:

    • 我有一个执行 xml 序列化的类,它在 ParallelizeExecution 类中使用,这个解决方案迫使我编辑 TaskLibrary.dll 而我不想/不能
    • 您使用的 XmlSerializer 属性(如 (XmlInclude) 向我表明您的自定义类包装了 XmlSerializer。如果是这种情况,我会考虑修改该类以实例化 XmlSerializer,就像我上面建议的那样——这将允许您在不修改 TaskLibrary.dll 的情况下添加类。否则我认为你不走运。
    • 确实我有一个自定义 xml 序列化程序,但它在 TaskLibrary.dll 中
    • 所以你真的根本不使用内置的XmlSerializer?您使用的是完全自定义的,但它利用了内置属性?在这种情况下,我们可能无法帮助您——您处于未知领域,因为这里没有人知道您的序列化程序是如何工作的。
    • 原谅我,我使用了一个自定义的 xml 序列化器,它反过来包装了内置 XmlSerializer 的功能。问题是:这个“包装器”在我不想改变的 dll 里面。我正在寻找一种解决方法,例如让“克隆”方法创建正确类型的对象,但我对这种方法没有运气。
    猜你喜欢
    • 2015-01-21
    • 2014-01-10
    • 2020-06-26
    • 2012-02-20
    • 2013-09-06
    • 2015-06-01
    • 2011-12-27
    • 1970-01-01
    • 2023-03-04
    相关资源
    最近更新 更多