Сериализация списка анонимных делегатов - PullRequest
3 голосов
/ 24 октября 2009

Этот вопрос может быть очень похож на мой, но я не вижу ответа, в котором я нуждаюсь. У меня есть класс с именем 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().

1 Ответ

4 голосов
/ 24 октября 2009

Обычно бессмысленно сериализовать делегата. Обычно вы можете пометить поля делегата как [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;}
}

Как видите - не всегда тривиально (это самый простой пример).

...