Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Распределённые приложения и сеть > Сериализация неизвестного объекта.


Автор: neutrino 2.3.2007, 09:52
Приветствую!

Архитектура следующая: веб-сервис состоит в основном из одного класса - MonitoringEngine, который выполняет комманды ICommand. Типов комманд много и в момент выполнения MonitoringEngine'у неизвестно какая именно комманда выполняется. Он знает только интерфейс ICommand и ему этого достаточно для выполнения комманд.
Метод, который выполняет комманды называется MonitoringEngine.perform(ICommand command). Oн возвращает объект класса CommandResponse, который содержит два поля: первое типа bool (успешно ли было выполнение комманды) и второе типа object, которое содержит объект результата выполнения комманды. Есть комманды у которых нет этого объекта (он null), есть комманды с различными классами объектов результата (список, какой-нибудь класс ...).

Вопрос: Как сериализировать этот CommandResponse? Я не могу знать в момент выполнения какие именно данные содержит этот класс. Только самa комманда знает что ей необходимо вернуть в CommandResponse.

Премного благодарен за любую помощь.

С уважением, нейтрино.

Автор: tol05 2.3.2007, 10:13
Как вариант: 
1 - Если поле типа object может содержать объект пользовательского типа - сделать этот тип серилизуемым (встроенные типы сами серилизуемые, так что там проблем не будет). Далее, после возврата объекта CommandResponse спокойно отдавать его серилизатору, он сам все проверит и серилизует
2 - рефлексия. Проверять поддерживает ли возвращенный объект интерфейс ISerializable и если да, отдавать его серилизатору.

Автор: neutrino 5.3.2007, 18:20
Цитата(tol05 @  2.3.2007,  09:13 Найти цитируемый пост)
Если поле типа object может содержать объект пользовательского типа - сделать этот тип серилизуемым (встроенные типы сами серилизуемые, так что там проблем не будет). Далее, после возврата объекта CommandResponse спокойно отдавать его серилизатору, он сам все проверит и серилизует

Как сериализатор может знать что находится в поле типа object?

Код

namespace core.commands
{
    /// <summary>
    /// Class represents response of command.
    /// </summary>
    [Serializable]
    public class CommandResponse
    {
        private object data;
        private bool succeed;

        public CommandResponse()
        {
        }

        public CommandResponse(bool succeed, object data)
        {
            this.data = data;
            this.succeed = succeed;
        }

        public object getData()
        {
            return data;
        }

        public bool commandsucceed()
        {
            return succeed;
        }
    }
}

Может ему необходимо прописать что-то вроде:
Код

if (data is ArrayList)
{
// Serialize data as ArrayList
}
else if (data is ...)
{
...
}
else ...

Автор: mr.DUDA 5.3.2007, 23:42
Цитата(neutrino @  5.3.2007,  17:20 Найти цитируемый пост)
Как сериализатор может знать что находится в поле типа object?

А он (десериализатор) и не знает, в отличие от сериализатора (которому доступна полная инфа о типах свойств и методов объекта). Что он может узнать по бинарному содержимому стрима smile ? Всё зависит от типа сериализации (включается ли в результат имя конкретного типа объекта, или нет).

Автор: tol05 6.3.2007, 10:27
Про десерилизатор разговора не было smile Кстати, я бы не стал включать в файл всякие дескрипшины, десерилизовать в необходимый объект, если эксепшион, то значит, не судьба.
А о серилизаторе - действительно, лажу спорол, нет у них внутри Serialize() проверок на интерфейс. 
Реализаций может быть много. Например, 
Код

if (data is ArrayList)
{
// Serialize data as ArrayList
}
else if (data is ...)
{
...
}
else ...


можно заменить на 
Код

try
{
myFormatter.Serialize(myStream, data);
}
catch (SerializationException e) 
{
    Console.WriteLine("Failed to deserialize. May be data don't support Serilialize oprration? Message: " + e.Message);
     throw;
}

в этом случае, если когда-нибудь добавится еще один вид коллекции или класса, не прийдется дописывать новые проверки

или 
Код

if(data is ISerializable)
{
myFormatter.Serialize(myStream, data);
}


или
Код

MethodInfo mi = data.GetType().GetMethod("GetObjectData");
if(!mi.Equals(null))
{
data.GetType().InvokeMember(...)
}


или что-то еще в этом духе

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)