System runtime serialization serializationexception не удалось найти сборку

Обновлено: 06.07.2024

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

Когда я пытаюсь выполнить десериализацию на стороне сервера после сериализации, у меня нет проблем.

Я пытался настроить подшивку, которая тоже не сработала. Я очень ценю, если кто-нибудь может мне помочь.

У клиента есть ссылка на сборку, содержащую класс?

в соответствии с тем, что я читал, я должен сделать что-то вроде этого, люди говорят о .dll и т. д., но как я могу это сделать?

Ответы 2

Если я правильно угадаю, у вас 2 проекта - «Мульти-клиент» и «Мульти-сервер». Вы сериализуете объект, определенный в «Мульти-сервере», а затем у вас есть копия этого класса в «Мульти-клиенте».

Итак, вы сериализуете объект «MultiServer.SomeClass», а затем хотите сделать его «MultiClient.SomeClass». Это не сработает.

Вам необходимо создать проект dll общий (назовем его «MultiCommon», где вы разместите свой класс и будете ссылаться на него как «MultiServer», так и «MultiClient». Таким образом, вы будете сериализовать и десериализовать, а не «MultiServer.SomeClass» "но" MultiCommon.SomeClass ".

Похоже, вы используете BinaryFormatter , и в этом случае, честно говоря, я думаю, что наиболее ценным советом будет: не делай этого. Формат данных BinaryFormatter в основном привязан к конкретным деталям реализации, поэтому очень сложно: иметь разный код на разных концах (что означает: развертывание очень сложно и хрупко - везде нужно изменить в то же время) или b: пересмотреть реализацию со временем.

Честно говоря, я настоятельно рекомендую поискать альтернативные инструменты сериализации. Я сильно предвзято, но protobuf-net хорошо работает с очень для этого типа сценария; он по-прежнему «двоичный» (то есть: не текстовый), но не привязан к деталям внутренней реализации. Он быстрый (обычно намного быстрее, чем BinaryFormatter ), эффективный (обычно требуется гораздо меньше пропускной способности, чем BinaryFormatter ), бесплатный и обычно очень легко применяется к существующей объектной модели; обычно это означает переход от этого:

Некоторые сведения относятся к предварительной версии продукта, в которую до выпуска могут быть внесены существенные изменения. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.

Исключение, которое выдается при возникновении ошибки во время сериализации или десериализации.

Примеры

Комментарии

SerializationException использует HRESULT COR_E_SERIALIZATION со значением 0x8013150C.

SerializationException использует реализацию по умолчанию Equals , которая поддерживает равенство ссылок.

Список начальных значений свойств для экземпляра SerializationException, см. в разделе SerializationException конструкторы.

Конструкторы

Инициализирует новый экземпляр класса SerializationException стандартными свойствами.

Инициализирует новый экземпляр класса SerializationException из сериализованных данных.

Свойства

Возвращает коллекцию пар «ключ-значение», предоставляющую дополнительные сведения об исключении.

Получает или задает ссылку на файл справки, связанный с этим исключением.

Возвращает или задает HRESULT — кодированное числовое значение, присвоенное определенному исключению.

Возвращает экземпляр класса Exception, который вызвал текущее исключение.

Возвращает или задает имя приложения или объекта, вызывавшего ошибку.

Получает строковое представление непосредственных кадров в стеке вызова.

Возвращает метод, создавший текущее исключение.

Методы

Определяет, равен ли указанный объект текущему объекту.

При переопределении в производном классе возвращает исключение Exception, которое является первопричиной одного или нескольких последующих исключений.

Служит хэш-функцией по умолчанию.

При переопределении в производном классе задает объект SerializationInfo со сведениями об исключении.

Возвращает тип среды выполнения текущего экземпляра.

Создает неполную копию текущего объекта Object.

Создает и возвращает строковое представление текущего исключения.

События

Возникает, когда исключение сериализовано для создания объекта состояния исключения, содержащего сериализованные данные об исключении.

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

Когда я пытаюсь выполнить десериализацию на стороне сервера после сериализации, проблем нет.

Я пытался настроить переплет, который тоже не работал. Я очень ценю, если кто-нибудь может мне помочь.

2 ответа

Если я правильно угадаю, у вас есть 2 проекта - «Мульти-клиент» и «Мульти-сервер». Вы сериализуете объект, определенный в «Мульти-сервере», а затем получаете копию этого класса в «Мульти-клиенте».

Итак, вы сериализуете объект «MultiServer.SomeClass», а затем хотите сделать его «MultiClient.SomeClass». Это не сработает.

Вам необходимо создать проект common dll (назовем его «MultiCommon», в который вы поместите свой класс, и ссылаться на него как «MultiServer», так и «MultiClient». Таким образом, вы выполните сериализацию и десериализуйте не "MultiServer.SomeClass", а "MultiCommon.SomeClass".

Похоже, вы используете BinaryFormatter , и в этом случае, честно говоря, я думаю, что наиболее ценным советом будет: не делайте этого . Формат данных BinaryFormatter в основном привязан к конкретным деталям реализации, что очень затрудняет: иметь разный код на разных концах (что означает: развертывание очень сложно и хрупко - везде нужно изменить на в то же время ), или b: со временем пересмотреть реализацию.

Откровенно говоря, я настоятельно рекомендую поискать альтернативные инструменты сериализации. Я сильно предвзят, но protobuf-net очень работает для этого типа сценария; он по-прежнему является «двоичным» (то есть не текстом), но не привязан к деталям внутренней реализации. Он быстрый (обычно намного быстрее, чем BinaryFormatter ), эффективный (обычно требуется гораздо меньше пропускной способности, чем BinaryFormatter ), бесплатный и обычно очень легко применим к существующей объектной модели; обычно это означает:

Итак, я нашел кучу потоков в этой теме, но я не думаю, что нашел тот, который еще не применяется.

В основном мой .exe загружает файл .dll(MyAssembly), который выполняет сериализацию и загрузку. Очевидно, он сериализуется довольно хорошо.

У кого-нибудь есть идеи? Я не понимаю, как он не может найти сборку, вызывающую код!

Является ли DLL в той же папке, что и EXE?
Я вижу, что вы сериализуете/десериализуете объект, который живет в DLL ( "MyAssembly" ). При десериализации форматтер определяет имя типа из сериализованных данных и пытается найти этот тип в сборке в основной исполняемой папке, то есть в папке EXE.
Решение. Переместите папку DLL в EXE. Существует способ заставить форматтер выполнять поиск в другой сборке, захватить событие AppDomain.AssemblyResolve и вернуть вашу DLL. См. MSDN.

Ну, я использовал трюк, который сработает!

используйте связующее для двоичных форматов, например:

Я хотел бы построить Sean Ed-Man , что хорошо, но doesn Я работаю в моем случае.

Если вы можете создать экземпляр класса, но BinaryFormatter не может его решить, это может сработать для вас.

В моем случае вызывающая сборка ( PluginAssembly для этого примера) запускается как плагин из исполняемого файла в виде zip файла. По какой-то причине я могу напрямую разрешить класс (из NeededAssembly ) при создании экземпляра, но BinaryFormatter не может его решить. NeededAssembly , конечно, включен как ссылка на проект PluginAssembly , поэтому я могу создать экземпляр. Я не знаю, почему BinaryFormatter отличается.

Несмотря ни на что, это то, что сработало для меня:

Конечно, не забудьте его использовать:

В основном я просто получаю typeof для необходимого класса, который работает.

То, что я вижу в вашем коде как с сериализацией, так и с десериализацией, - это использование класса System.IO.Path вместо фактического пути к файлу. Обычно я выполняю это следующим образом:

Обратите внимание на две вещи: выполнение Deserialize, поскольку обрабатывает объект, являющийся нулевым или не ожидаемым. Также я не злоупотребляю использованием var.

Я бы проверял, отвечает ли Марк Гравелл здесь: "Одним из вариантов было бы переместить этот тип в библиотеку dll, которая и другие ссылки на проекты - тогда он определяется только один раз, и он будет счастлив"

В моем случае я временно создал копию класса, который я собирался сериализовать (в сборке, выполняющей сериализацию) в начале разработки, но забыл об этом при десериализации! Таким образом, десериализатор никогда не имел доступа к тому же классу, который выполнял сериализацию!

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

Существует еще одно решение этой проблемы, которое заключается в перечислении папки, содержащей сборку в App.config. Вы делаете это, добавляя элемент probing , например:

У меня был конкретный случай SerializationException, описанный OP, и я нашел относительно простое решение. В моем случае я реализую метод расширения DeepClone, используя технику BinaryFormatter. Мое приложение также использует плагины, сборки, которые я загружаю программно. Я столкнулся с исключительной ситуацией SerializationException, когда был вызван метод BinaryFormatter.Deserialize для объекта, класс которого содержится в плагине.

Я нахожу это очень странным, потому что по определению содержащая сборка загружается в мой AppDomain. (Я не смог бы вызвать метод расширения объекта, если это не так!) По-видимому, BinaryFormatter не проверяет домен приложения для разрешения сборок.

Многие из предлагаемых здесь решений для решения этой проблемы, по-видимому, связаны с жестким кодированием имени сборки или класса в пользовательском SerializationBinder. Это бесполезно, так как я хочу, чтобы мой метод DeepClone был как можно более универсальным. Мой ответ на эту проблему (показанный ниже) перехватывает событие AssemblyResolve в текущем домене приложений, а затем ищет в домене приложений (используя LINQ) запрошенную сборку. Не требуется жестко закодированная сборка или имена классов.

У меня была проблема с этим исключением. Я пишу плагин WPF для стороннего приложения. Приложение загружает мою сборку, которая должна десериализовать тип из другой библиотеки DLL, например MyType, которая находится в закрытой сборке, добавленной в качестве ссылки на мой плагин, и в том же каталоге, что и библиотека плагина.

Что мне кажется странным, так это то, что я могу создать экземпляр MyType в плагине, но он вызывает это исключение при десериализации в том же классе.

Решение для меня было предложено RoadBump и оно очень простое, но я не понимаю, почему окружающий код может найти сборку (если он не может, этот метод не будет работать), но вызов десериализации в том же коде может ' т.

Читайте также: