如何在T不可序列化时序列化List <t> </t>

时间:2011-02-21 02:40:13

标签: c# .net

案例:

将一个不可序列化的参数传递给AppDomain。

以下是我想在远程域中调用的一些方法;

public RemoteClass
{
  public Test(Class1 obj);
  public Test(List<Class1> obj);
}

定义:

Class1    :   un-serializable

[Serializable]
Class2 : Class1  , ISerializable  //mark Class2 serializable
{
    //.....
}

以下代码用于测试:

using (MemoryStream s = new MemoryStream())
{
    BinaryFormatter f = new BinaryFormatter();
    f.Serialize(s, obj);
}

测试结果:

obj                                      result

Class1 obj=new Class1();                 exception

Class1 obj=new Class2();                 success

List<Class1> obj=new List<Class1);       exception  when obj contain some element;
obj.Add(new Class1();   

List<Class1> obj=new List<Class1);       exception  when obj contain some element; //how???
obj.Add(new Class2();

List<Class2> obj=new List<Class2);       success;
obj.Add(new Class2();   

Class1不是可序列化的calss,我无法修改它,因此我定义了继承自Class1并实现ISerializable的Class2。当方法在测试结果中需要Class2的实例并且此解决方案成功时,我可以传递Class1的实例,但是对于List<Class1>,这不起作用。

8 个答案:

答案 0 :(得分:3)

如何将List<Class1>实例转换为列表List<Class2>(只要您在Class2上声明合适的构造函数,以下内容就可以正常工作):

// using System.Linq;
List<Class1> inputList = MyInputList();
List<Class2> outputList = inputList.ConvertAll<Class2>(a => new Class2(a));

然后,您应该可以将List<Class2>序列化。

您发现需要将序列化列表转换回List<Class>,然后才能在接受List<Class1>的任何地方使用它 - 上面的变体也应该反过来。< / p>

答案 1 :(得分:3)

尝试为List<Class1>创建serialization surrogate

答案 2 :(得分:2)

List<T>不可序列化时,您无法序列化T

答案 3 :(得分:0)

序列化对象时,所有子对象也必须是可序列化的。

List<T>是可序列化的,但如果T也可序列化,则只能对其进行序列化。我不认为这条规则有任何例外。

您有什么理由让T无法序列化?在大多数情况下,您只需在类名上方添加[Serializable],这就是您需要做的一切!

答案 4 :(得分:0)

内置BinaryFormatter不支持此功能。如果要序列化未标记为Serializable的类,则需要构建不检查Serializable属性的自定义序列化程序。

这当然会有很多工作。

答案 5 :(得分:0)

如果通过序列化意味着将其转换为各种二进制格式。您可以使用反射手动执行此操作。它变得棘手但可以完成,甚至比内置的二进制序列化更有效。

如果您想使用标准的.Net binary serialization,那么您运气不好,除非您愿意将[Serializable]属性添加到T或在T上实现ISerializable。

如果您对手动编码序列化程序感兴趣,可以查看我用于媒体浏览器的some of the code。根据您想要支持的对象的复杂程度,它会变得棘手。除非绝对必要,否则不建议编写自己的序列化程序。

答案 6 :(得分:0)

你不能使用BinaryFormatter - 除非基类型是(/是)可序列化的,否则它不会让你。但是,您可以序列化为xml并只传递字符串或字节[] - XmlSerializer不太特别:

using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;
using System;

public class Class1 { }
public class Class2 : Class1{}

static class Program {

    static void Main() {

        List<Class2> c2 = new List<Class2>();
        var ser = new XmlSerializer(typeof(List<Class1>), new[] {typeof(Class1), typeof(Class2)});

        List<Class1> objects = new List<Class1>(), clone;
        objects.Add(new Class2());
        objects.Add(new Class2());
        objects.Add(new Class2());
        using (var ms = new MemoryStream())
        {
            ser.Serialize(ms, objects);
            ms.Position = 0;
            clone = (List<Class1>)ser.Deserialize(ms);
        }
        Console.WriteLine(clone.Count);
    }
}

这里的差异显然是XmlSerlializer发送公共成员,而不是字段。我也知道如果你想要二进制文件,我自己的序列化程序可以为你做这个。

答案 7 :(得分:0)

如果buildIn Serializer无法满足您的需求,请尝试其他选择:sharpserializer