我正在程序结尾处尝试序列化类Reference
的对象。引发序列化异常,该异常抱怨“ DataAnalysis.Reference + <> c__DisplayClass4”未标记为可序列化。
最初,我有两个没有Serializable
属性的代表,因此我尝试了一下,但是没有任何改变。类Cacheable
和Operation
已经被标记为Serializable
-实际上,在我介绍Reference
类之前,这两个类的序列化工作都很好。
我什至不知道c__DisplayClass4是什么意思。因此,很抱歉,但是我不知道将1 MB以上的源代码中的其他部分发布到这里来帮助您解决问题,因为最终我将发布所有内容。
正如我所说,在引入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);}
}
}
}
编辑:我选择了taffer的第一个解决方案(避免在委托中使用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
类。但是原理很清楚。
答案 0 :(得分:1)
由于在第二个构造函数中初始化字段的方式而导致错误:
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 :
不要在lambda中捕获封闭方法的局部变量和参数。该字段应该是委托的参数。
解决方案2 :
实施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));
}
请注意,反序列化非静态方法的委托可能会出现问题。如果setter或getter是实例方法,也许应该检查Delegate.Method
中的GetObjectData
属性并抛出异常。