2011-02-21 2 views
4

Корпуса:как сериализовать Список <T> при Т не сериализуемый

Проходит unserializable перекрестного параметр 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, и я не могу его изменить, поэтому я определяю Class2, который наследует Class1 и реализует ISerializable. Я могу передать экземпляр Class2, когда метод нуждается в экземпляре Class1 в результате теста, и это решение успешно, однако для List<Class1> это не сработает.

+0

вы можете дать нам пример класса 1, которые могут вызвать проблемы и похожа на вашу проблему? Кажется, ваш вопрос должен быть: «Как я могу сделать этот класс сериализуемым?» – Steve

+0

Class1 не является сериализуемым, и я не могу его изменить, поэтому я определяю Class2: Class1, Iserializable; теперь Class2 является сериализуемым, я передам Class2, когда необходимо, чтобы метод Class1 – Clover

ответ

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>. Вариант выше должен работать так же хорошо, как и наоборот.

+0

yes Я могу преобразовать List в список , но удаленному классу нужен Список , и я не могу изменить удаленный класс – Clover

+0

@Clover. Вы должны определить второй удаленный метод, который принимает «Список » - этот удаленный метод должен преобразовать список обратно в «Список », а затем вызовите первый удаленный метод. – Justin

2

Вы не можете сериализовать List<T>, когда T не является сериализуемым.

+0

SerializationException был брошен, когда я пытаюсь выполнить сериализацию списка , и я могу сериализовать T, когда T не является сериализуемым – Clover

0

Когда вы сериализуете объект, все дочерние объекты также должны быть сериализуемыми.

List<T> является сериализуемым, но его можно сериализовать, если T также сериализуем. Я не думаю, что есть исключения из этого правила.

Какая у вас причина для T, чтобы не быть сериализуемым? В большинстве случаев все, что вам нужно сделать, это добавить [Serializable] над именем класса, и это все, что вам нужно сделать!

+0

T определен в другом компоненте, который я не могу его изменить – Clover

0

Встроенный BinaryFormatter не поддерживает это. Если вы хотите сериализовать классы, которые не помечены как Serializable, вам нужно создать собственный сериализатор, который не проверяет атрибут Serializable.

Это, конечно, было бы большой работой.

+0

да, я различаю Class2, который наследует Class1 и реализует ISerializable, поэтому Class2 является сериализуемым, но List также не является сериализуемым, хотя реальный тип - Class2 – Clover

0

Если путем сериализации вы имеете в виду, преобразуйте его в двоичный формат сортировки. Вы можете сделать это вручную, используя отражение. Это сложно, но может быть сделано, даже более эффективно, чем встроенная двоичная сериализация.

Если вы хотели бы использовать стандартный .Net binary serialization вы не повезло, если вы не готовы, чтобы добавить атрибут [Serializable] Т или реализовать ISerializable на Т.

Если вы заинтересованы в руке кодирования сериализатор можно посмотреть на some of the code Я использую для медиа-браузера. Это становится сложным в зависимости от того, насколько сложны объекты, которые вы хотите поддержать. Не рекомендовал бы писать свой собственный сериализатор, если это абсолютно необходимо.

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 посылает представителей общественности, а не поля. Я также знаю, что мой собственный сериализатор может сделать это для вас, если вы хотите использовать двоичный файл.

0

Если Buildin Serializer не способен, что вы хотите, попробуйте альтернативу: sharpserializer

Смежные вопросы