2016-05-06 6 views
0

У меня возникли проблемы с попыткой выполнить десериализацию с использованием protobuf-net при использовании более сложной иерархии, включающей также дженерики и наследование.Наследование protobuf-net с общим типом

Как определить динамическую иерархию типов?

Интересно то, что сериализация работает отлично, но десериализации терпит неудачу с исключением с сообщением: «Не было возможности подготовить сериалайзер для: Serialization.command.ICommand»

См код ниже I используя:

[ProtoContract] 
public abstract class AbstractEntity 
{ 

    public AbstractEntity() 
    { 

    } 
    protected AbstractEntity(int integer) 
    { 
     this.integer = integer; 
    } 

    private int noSerializable = 0; 
    [ProtoMember(1)] 
    public int NoSerializable { get { return noSerializable; } 
     set { noSerializable=value; } 
    } 
} 


[ProtoContract] 
public class Entity:AbstractEntity 
{ 
    public Entity() : base() 
    { 

    } 
    public Entity(int integer) : base(integer) 
    { 
    } 
    [ProtoMember(2)] 
    public String Name { get; set; } 
    [ProtoMember(3)] 
    public String Surname { get; set; } 
    [ProtoMember(4)] 
    public int Age { get; set; } 
} 

[ProtoContract] 
public interface ICommand 
{ 
    void Execute(); 
} 

[ProtoContract] 
public abstract class AbstractCommand: ICommand 
{ 
    public abstract void someAbstractMet(); 
    public void Execute() 
    { 

    } 
} 

[ProtoContract] 
public class AbstractEntityCommand<T>:AbstractCommand where T:AbstractEntity 
{ 

    [ProtoMember(1)] 
    public T Entity { set; get; } 

    public AbstractEntityCommand() 
    { 

    } 
    public AbstractEntityCommand(T entity) 
    { 
     Entity = entity; 
    } 

    public override void someAbstractMet() 
    { 

    } 
} 

[ProtoContract] 
public class UpdateEntityCommand<T>:AbstractEntityCommand<T> where T:AbstractEntity 
{ 
    public UpdateEntityCommand() 
    { 

    } 

    public UpdateEntityCommand(T entity):base(entity) 
    { 

    } 
    public override void someAbstractMet() 
    { 

    } 

} 


class Program 
{ 
    static void Main(string[] args) 
    { 


     var entity = new Entity(4); 
     Console.WriteLine("Using Protobuf"); 
     //first define dinamicaly the hierarchy - see ProtoInclude attribute 
     RuntimeTypeModel.Default.Add(typeof (AbstractEntity), true).AddSubType(7, typeof (Entity)); 
     AbstractEntity absEnt = entity; 
     bites = absEnt.ProtoBufSerialize(); 

     thirdEntity = (Entity)bites.ProtoBufDeserialize<AbstractEntity>(); 
     Console.WriteLine("Name=" + thirdEntity.Name + " Surname=" + thirdEntity.Surname + " Age=" + thirdEntity.Age + " integer=" + thirdEntity.TheInt + " No serializable field = " + thirdEntity.NoSerializable); 

     // Console.ReadKey(); 

     Console.WriteLine("Test for generics"); 

     RuntimeTypeModel.Default.Add(typeof(ICommand), true).AddSubType(70, typeof(AbstractCommand)); 

     RuntimeTypeModel.Default.Add(typeof(ICommand), true).AddSubType(80, typeof(AbstractEntityCommand<>)); 
     RuntimeTypeModel.Default.Add(typeof(ICommand), true).AddSubType(90, typeof(UpdateEntityCommand<>)); 

     ICommand genCommand = new UpdateEntityCommand<Entity>(entity); 


     bites = genCommand.ProtoBufSerialize(); 
     var concreteCmd = bites.ProtoBufDeserialize<UpdateEntityCommand<Entity>>(); 
     var unknownCmd = bites.ProtoBufDeserialize<ICommand>(); 

     Console.ReadKey(); 
    } 

Все работает нормально, пока не попытаюсь десериализовать ICommand.

Что мне здесь не хватает?

ответ

0

Дженерики не проблема, protobuf-net поддерживает их. Проблема в том, что у вас есть интерфейс как корневой объект. Хотя прекрасно сериализовать интерфейсы как члены, интерфейс интерфейса не может выступать в качестве корневого объекта.

Поэтому

bites.ProtoBufDeserialize<ICommand>(); 

генерирует исключение.

+0

К сожалению, это не сработает. Даже если корень является абстрактным классом, поведение такое же. Любые другие идеи? –

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