2015-05-09 3 views
1

Есть ли возможность сериализации классов, содержащих несериализуемые элементы?Сериализовать классы, содержащие несериализуемые элементы

Пример: У меня есть класс Инструкцию, которая имеет два элемента:

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

Проблема в том, что тип элемента Op находится в 3-й партии библиотеки, и я не могу сделать это сериализации , Я попробовал BinaryFormatter и ProtoBuf, но оба провалились без маркировки Op-члена.

Кто-нибудь знает решение сериализации моего объекта?

ответ

1

Очевидно, что если часть класса не может быть сериализована, вы не можете сериализовать эту часть, но можете ее игнорировать (и при десериализации) значение параметра по умолчанию, возможно, null.

Вы можете использовать атрибут [ProtoIgnore], чтобы отметить Op свойства, если вы используете ProtoBuf, или [NonSerialized] атрибутов для BinaryFormatter.

+0

Но что, когда мне нужен член для последующего использования? – user4653488

+0

Ну, вы не можете сериализовать то, что не сериализуемо. Вы ничего не можете сделать с этим без обратного проектирования классов и посмотреть, как вы можете принудительно сериализовать. Может быть, 'OpCode' использует собственные ресурсы? –

1

Один из способов - создать класс оболочки над Opcode и использовать объект этого класса-оболочки в классе инструкций для сериализации и других целей в вашем приложении. Таким образом, вы можете избавиться от каких-либо ограничений со сторонней библиотекой.

0

Вы могли:

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. Таким образом вы бы сериализовали Name кода op (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.

+0

Это возможный способ для OpCode, но он не будет работать для объекта правильно? Я имею в виду, что операнд может иметь несколько типов. – user4653488

+0

@user См. Расширенный ответ. К сожалению, protobuf не поддерживает сериализацию примитивных типов ('int',' short', ...) внутри 'object' – xanatos

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