Исключение: DataAnalysis.Reference + <> c__DisplayClass4 не сериализуем - PullRequest
1 голос
/ 19 апреля 2019

Я пытаюсь сериализовать объекты класса Reference в конце моей программы.Выдается исключение сериализации, которое жалуется на то, что «DataAnalysis.Reference + <> c__DisplayClass4» не помечен как сериализуемый.

Изначально у меня было два делегата без атрибута Serializable, поэтому я попробовал, но это ничего не изменило.Классы Cacheable и Operation уже помечены как Serializable - и на самом деле сериализация их обоих прекрасно работала до того, как я ввел класс Reference.

Я даже не знаюзнать, что означает c__DisplayClass4.Поэтому я прошу прощения, но я не знаю, какие другие части моего 1-мегабайта + исходный код размещать здесь, чтобы помочь вам решить проблему, потому что в конце я буду публиковать все.

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

using System;
using System.Reflection;

namespace DataAnalysis
{
    /// <summary>
    /// Description of Reference.
    /// </summary>
    [Serializable]
    public class Reference
    {
        [Serializable]
        public delegate void ReferenceSetter(Operation op, Cacheable c);

        [Serializable]
        public delegate Cacheable ReferenceGetter(Operation op);

        readonly ReferenceGetter refGetter;
        readonly ReferenceSetter refSetter;

        public Reference(ReferenceGetter getter, ReferenceSetter setter)
        {
            refGetter = getter;
            refSetter = setter;
        }

        public Reference(FieldInfo operationField)
        {
            refGetter = (op => (Cacheable)operationField.GetValue(op));
            refSetter = ((op, value) => operationField.SetValue(op, value));
        }

        public Cacheable this[Operation op]
        {
            get {return refGetter(op);}
            set {refSetter(op, value);}
        }
    }
}

Редактировать: Я выбрал первое решение для таффера (избегайте использования FieldInfo внутри делегата):

public class Reference
{
    public delegate void ReferenceSetter(Operation op, Cacheable c);
    public delegate Cacheable ReferenceGetter(Operation op);

    readonly FieldInfo opField;
    readonly ReferenceGetter refGetter;
    readonly ReferenceSetter refSetter;

    public Reference(ReferenceGetter getter, ReferenceSetter setter)
    {
        refGetter = getter;
        refSetter = setter;
    }

    public Reference(FieldInfo operationField)
    {
        opField = operationField;
    }

    public Cacheable this[Operation op]
    {
        get 
        {
            if (opField != null) return (Cacheable)opField.GetValue(op);
            else return refGetter(op);
        }
        set 
        {
            if (opField != null) opField.SetValue(op, value);
            else refSetter(op, value);
        }
    }
}

Пока не отточено, я, вероятно, наконец-то буду использовать абстрактный класс Reference с двумя реализациями.Но принцип становится понятным.

1 Ответ

1 голос
/ 19 апреля 2019

Вы получаете ошибку из-за способа инициализации ваших полей во втором конструкторе:

public Reference(FieldInfo operationField)
{
    // operationField is captured in the lambda below, which causes to generate an inner class
    // where operationField will be a field so can be accessed by the method of the lambda body
    refGetter = (op => (Cacheable)operationField.GetValue(op));
    refSetter = ((op, value) => operationField.SetValue(op, value));
}

Решение 1 :

Не фиксировать локальные значения и параметры метода включения в лямбду. Поле должно быть скорее параметром делегата.

Solution2 :

Реализация ISerializable и предоставление настраиваемой сериализации:

void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
    info.AddValue("getter", refGetter);
    info.AddValue("setter", refSetter);
}

// the special constructor needed for deserialization
private Reference(SerializationInfo info, StreamingContext context)
{
    refGetter = (ReferenceGetter)info.GetValue("getter", typeof(ReferenceGetter));
    refSetter = (ReferenceSetter)info.GetValue("setter", typeof(ReferenceSetter));
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...