Сериализация списка анонимных делегатов
-
06-07-2019 - |
Вопрос
Этот вопрос может быть, он очень похож на мой, но я не вижу в нем нужного мне ответа.У меня есть класс, который называется CASM
, который имеет List<Action>
.Я хочу сериализовать этот класс (используя BinaryFormatter
или что-то подобное).Этот класс и все классы, на которые ссылаются в Action
у вас есть правильный [Serializable]
и [NonSerializable]
атрибуты.
Проблема возникает при попытке сериализации - она выдает эту ошибку:
Type 'CASM.CASM+<>c__DisplayClass2c' in Assembly 'CASM, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null' is not marked as serializable.
Это <>c__DisplayClass2c
это автоматически сгенерированный внутренний класс, который содержит различные типы анонимных делегатов, которые я использую в своем приложении.Однако, как мы можем видеть из приведенного ниже изображения, это не так [Serializable]
:
альтернативный текст http://bayimg.com/image/maebbaacj.jpg
Каков был бы наилучший способ изменить мое приложение, чтобы оно действительно работало?Сделать свой собственный <>c__DisplayClass2c
-ввести класс и сделать его сериализуемым?Или есть способ получше?
Редактировать: В конце концов я просто создал свой собственный класс, вместо автоматически созданного.Я также помогаю с отладкой, на самом деле имея описательное имя, а не просто b__12()
.
Решение
Обычно сериализовывать делегат не имеет особого смысла.Обычно вы бы предпочли пометить поля делегирования как [NonSerialized]
, и воссоздайте его при необходимости.Если ваше главное намерение является честно говоря, чтобы сохранить делегатов, я бы рекомендовал подумать о совершенно другом подходе.
Кроме того, обратите внимание, что BinaryFormatter
является хрупким, если вы планируете хранить данные в течение любого периода времени (но приемлемо для временных данных).
Чтобы посмотреть дальше, я подозреваю, что нам нужно было бы взглянуть на какой-нибудь воспроизводимый код.
Обновить:на самом деле, я подозреваю тебя мог бы сериализуйте его, написав свои собственные явные классы захвата (а не сгенерированные компилятором).Но я все еще считаю, что эта концепция в корне порочна.А писать уроки захвата от руки совсем не весело.
Для рассмотрения вопросов в комментариях;при длительном хранении - потому что это такая чертовски хрупкая - что-то столь же простое, как переход с:
public int Value {get;set;}
Для
private int value;
public int Value {
get {return value;}
set {
if(value < 0) throw new ArgumentOutOfRangeException();
this.value = value;
}
}
уничтожит сериализацию;как и изменение сборок, названий типов, "забавно на это смотреть" и т.д.
Повторно делегаты;чтобы привести пример ручного захвата;вместо того , чтобы:
int i = ...
Predicate<Foo> test = delegate (Foo x) { return x.Bar == i;}
вы могли бы это сделать:
int i = ...
MyCapture cpt = new MyCapture(i);
Predicate<Foo> test = cpt.MyMethod;
с
[Serializable]
class MyCapture {
private int i;
public MyCapture(int i) {this.i = i;}
public bool MyMethod(Foo x) {return x.Bar == i;}
}
Как видите - не всегда тривиально (это самый простой из примеров).