2014-02-04 2 views
0

Я пытаюсь вручную десериализовать объекты из MemoryStream, но MemoryStream будет иметь разные типы объектов в нем, и мне нужно вызвать соответствующий метод в зависимости от типа объекта. Например, это как MemoryStream отформатирован (тип объекта, то данные, повторяя):Десализируя различные типы объектов из MemoryStream эффективно

[object type (uint)][object data (variable length)][object type (uint)][object data (variable length)][object type (uint)][object data (variable length)] 

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

Один из способов будут использовать переключатель заявление так:

switch (objectType) { 
    case 0: 
     SomeClass.LoadFromMemoryStream(memoryStream); 
     break; 
    case 1: 
     SomeOtherClass.LoadFromMemoryStream(memoryStream); 
     break; 
    case 2: 
     EvenAnotherClass.LoadFromMemoryStream(memoryStream); 
     break; 
    ... 
} 

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

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

Я подозреваю, что могу сделать это с помощью генериков, но не понимаю, как настроить классы и методы для поддержки этого. Является ли оператор switch лучшим подходом? Если нет, то что?

+0

Создание игры через TCP? ^^ Не всегда хорошая идея. – AgentFire

+0

Создание игры, но это для загрузки карты из файла. Карта уже загружена в память с помощью байтового массива, и я использую MemoryStream для легкого чтения своих данных с помощью таких функций, как ReadUInt16() – Todd

+0

, почему вы не загружаете карту с диска? Кроме того, почему бы вам не использовать 4-байтную длину для каждого объекта переменной длины? – AgentFire

ответ

0

На мой взгляд, я сделаю следующее. 1.Define интерфейс,

public interface ISerializableType 
{ 
    uint TypeIdentity { get; } 

    void InitFromStream(Stream stream); 

    void ToStream(Stream stream); 
} 

2.Let все типы, которые вам необходимо поддерживать для реализации этого интерфейса. 3.Create завод класс, регистрировать все типы объектов, которые необходимо поддерживать

private IDictionary<uint, System.Type> _objectMap = new Dictionary<uint, System.Type>(); 

4.When для читает информацию из потока, в первую очередь проверить идентичность типа, а затем проверить против вашего контейнера чтобы узнать, можете ли вы его поддержать или нет, если хотите, затем захватите тип и создайте новый объект.

5. Установите новый объект в ISerializableType и вызовите метод InitFromStream.

var typeIdentity = ReadIdentityFromStream(stream); 
     if(_objectMap.ContainsKey(typeIdentity)){ 
      var type = _objectMap[typeIdentity]; 
      var obj = System.Activator.CreateInstance(type); 
      var iSerializable = obj as ISerializableType; 
      if (null != iSerializable) iSerializable.InitFromStream(stream); 
     }; 

Я надеюсь, что это поможет.

0

Что касается эффективности. Проверьте protobuf.

И относительно проблемы. При сохранении/загрузке состояния вам не следует работать с массивом объектов. Он должен быть полным типом, который самостоятельно выполняет все необходимые шаги по десериализации.

К примеру, десериализации этого

object[] mydata; 

бы от вас требуется случай переключателя или работает метод обнаружения типов объектов (долго и трудно поддерживать переключатель), вы могли бы на самом деле утилизировать атрибуты, чтобы сказать, что делать с каким объектом, но ..

Рассмотрим этот

public class Level 
{ 
    public IItem[] Item {get; set;} 
    public IRoom[] Room {get; set;} 
    public IMonster[] Monster {get; set;} 
    ... 
} 

public class ItemBook: IItem 
{ 
    public string Name 
    { 
     set { /* this code will be automatically executed during deserialization */ } 
    } 

    public ItemBook() 
    { 
     /* and this code */ 
    } 
} 

... 

десериализации Level является более эффективным.

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