Преобразование объекта в массив байтов в C#, отправка его через сокет, а затем преобразование обратно в объект

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

private static byte[] ObjectToByteArray2(Object obj)
    {
        if (obj == null)
            return null;
        BinaryFormatter bf = new BinaryFormatter();
        MemoryStream ms = new MemoryStream();
        bf.Serialize(ms, obj);
        return ms.ToArray();
    }

И преобразовать его обратно с помощью

private static Object ByteArrayToObject(byte[] arrBytes)
    {
        MemoryStream memStream = new MemoryStream();
        BinaryFormatter binForm = new BinaryFormatter();
        memStream.Write(arrBytes, 0, arrBytes.Length);
        memStream.Seek(0, SeekOrigin.Begin);
        Object obj = (Object)binForm.Deserialize(memStream);
        return obj;
    }

Проблема в том, что как только я отправляю этот массив байтов по сети в другое приложение, я не могу просто использовать этот метод для его обратного преобразования, я получаю сообщение об ошибке «Невозможно найти сборку 'test1s, версия = 1.0.0.0, культура = нейтральный, PublicKeyToken=null». test1s — это просто название маленькой серверной программы, которую я сделал, чтобы играть с этим. Очевидно, что приложению нужна дополнительная информация, чтобы преобразовать этот массив обратно в объект, так что я могу это сделать, или я неправильно решаю проблему?

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

Спасибо


person cost    schedule 14.11.2010    source источник
comment
На вашем месте я бы использовал отладчик, чтобы попытаться понять это. Если, конечно, вы не верите, что отладчик — мать всего зла. Если вы не понимаете, что я имею в виду, загрузите это: stackoverflow.com/questions/602138/   -  person YWE    schedule 14.11.2010


Ответы (4)


Здесь поможет множество готовых библиотек сериализации. У BinaryFormatter есть некоторые (IMO) нежелательные функции, в частности, он будет работать только с одной и той же (ну, в значительной степени) dll на обоих концах.

XmlSerializer, DataContractSerializer и JavaScriptSerializer являются хорошими реализациями на основе текста и будут нормально работать с совместимым контрактом на обоих концах (одинаковые свойства и т. д. — не обязательно одного и того же типа/версии).

Если у вас есть умеренные потребности в пропускной способности или вам нужна более высокая производительность процессора, я бы порекомендовал protobuf-net (предупреждение: я написал это), который является быстрым двоичным сериализатором, который может помочь.

person Marc Gravell    schedule 14.11.2010

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

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

Если требуется компактный формат, вы можете просмотреть буферы протокола Google.

person cdhowie    schedule 14.11.2010

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

person Alxandr    schedule 14.11.2010

Напишите свой собственный конвертер объектов из/в байты вместо использования BinaryStream.

Если вы настаиваете, переместите этот объект в его собственную сборку и добавьте его к обеим сторонам в качестве ссылки. Таким образом, .NET Framework должна иметь возможность десериализовать объект.

person Lex Li    schedule 14.11.2010