InvalidCastException при сериализации и десериализации

Разъяснение о obj.getClass() != getClass().

Этот оператор является результатом equals() являющийся недружелюбным наследованием. JLS (спецификация языка Java) определяет это, если A.equals(B) == true тогда B.equals(A) должен также возвратиться true. Если Вы опустите тот оператор наследующие классы, которые переопределяют equals() (и изменяются, то его поведение) повредит эту спецификацию.

Рассматривают следующий пример того, что происходит, когда оператор опущен:

    class A {
      int field1;

      A(int field1) {
        this.field1 = field1;
      }

      public boolean equals(Object other) {
        return (other != null && other instanceof A && ((A) other).field1 == field1);
      }
    }

    class B extends A {
        int field2;

        B(int field1, int field2) {
            super(field1);
            this.field2 = field2;
        }

        public boolean equals(Object other) {
            return (other != null && other instanceof B && ((B)other).field2 == field2 && super.equals(other));
        }
    }    

Выполнение new A(1).equals(new A(1)) кроме того, new B(1,1).equals(new B(1,1)) результат выделяет верный, как это должно.

Это выглядит все очень хорошим, но посмотрите, что происходит, если мы пытаемся использовать оба класса:

A a = new A(1);
B b = new B(1,1);
a.equals(b) == true;
b.equals(a) == false;

, Очевидно, это неправильно.

, Если Вы хотите гарантировать симметричное условие. a=b, если b=a и вызов принципа замены Лисков super.equals(other) не только в случае [1 113] экземпляр, но и проверка после на [1 114] экземпляр:

if (other instanceof B )
   return (other != null && ((B)other).field2 == field2 && super.equals(other)); 
if (other instanceof A) return super.equals(other); 
   else return false;

, Который произведет:

a.equals(b) == true;
b.equals(a) == true;

, Где, если a не ссылка [1 116], то это могло бы быть быть ссылкой класса A (потому что Вы расширяете его), в этом случае Вы звоните super.equals() также .

13
задан Community 23 May 2017 в 11:53
поделиться

3 ответа

Вы загрузили одну и ту же сборку дважды в разных контекстах загрузчика . Например, вы случайно загрузили XXX.Auditing с помощью Assembly.LoadFrom () , а затем какая-то другая (или ваша) сборка загрузила его нормально. Фактически, двоичный десериализатор мог быть тем, кто загрузил сборку второй раз, хотя я не знаю почему (нет опыта работы с ASP.NET).

4
ответ дан 2 December 2019 в 01:11
поделиться

Мне кажется, что у вас один и тот же класс в разных сборках (или веб-приложениях). BinaryFormatter включает метаданные типа в сериализацию, что означает, что будет работать только такая же сборка . 2 решения:

  • поместите этот тип в dll и укажите, что одиночная dll в обоих местах
  • использует сериализатор на основе контрактов

Лично я бы выбрал второй для огромного количества Причины не ограничиваются только этой. Возможные варианты:

  • XmlSerializer (xml; сериализует общедоступные поля и свойства; только «дерево»)
  • DataContractSerializer (xml; сериализует отмеченные поля и свойства (общедоступные или частные); "дерево" или " граф ")
  • protobuf-net (двоичный; сериализует отмеченные поля и свойства (общедоступные или частные);"
4
ответ дан 2 December 2019 в 01:11
поделиться

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

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

1
ответ дан 2 December 2019 в 01:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: