匿名方法序列化





4.00/5 (5投票s)
匿名方法序列化
引言
在 C# 中,匿名方法无法被序列化(除非它们不引用任何堆栈变量)。最简单的解决方案是为该方法生成的匿名类添加 [Serializable]
属性,但由于(据我所知)目前还无法做到这一点,因此我们必须使用这种“技巧”。
这是 Jeremy Thomas 版本的一个更新版本,可以在这里找到,改进之处在于它也支持嵌套委托和任何委托。
请注意,此代码未经充分测试。 另外请注意,匿名方法内部引用的任何内容也会被序列化,包括 this
。 这意味着,如果您序列化引用 this
的委托,然后再次反序列化并运行它,那么 this
将引用该对象的新的副本。
使用代码
formater.Serialize(stream, new SerializeDelegate(myDelegate));
代码
[Serializable]
public class SerializeDelegate : ISerializable
{
internal SerializeDelegate(Delegate delegate_)
{
this.delegate_ = delegate_;
}
internal SerializeDelegate(SerializationInfo info, StreamingContext context)
{
Type delType = (Type)info.GetValue("delegateType", typeof(Type));
//If it's a "simple" delegate we just read it straight off
if (info.GetBoolean("isSerializable"))
this.delegate_ = (Delegate)info.GetValue("delegate", delType);
//otherwise, we need to read its anonymous class
else
{
MethodInfo method = (MethodInfo)info.GetValue("method", typeof(MethodInfo));
AnonymousClassWrapper w =
(AnonymousClassWrapper)info.GetValue
("class", typeof(AnonymousClassWrapper));
delegate_ = Delegate.CreateDelegate(delType, w.obj, method);
}
}
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("delegateType", delegate_.GetType());
//If it's an "simple" delegate we can serialize it directly
if ((delegate_.Target == null ||
delegate_.Method.DeclaringType
.GetCustomAttributes(typeof(SerializableAttribute), false).Length > 0) &&
delegate_ != null)
{
info.AddValue("isSerializable", true);
info.AddValue("delegate", delegate_);
}
//otherwise, serialize anonymous class
else
{
info.AddValue("isSerializable", false);
info.AddValue("method", delegate_.Method);
info.AddValue("class",
new AnonymousClassWrapper
(delegate_.Method.DeclaringType, delegate_.Target));
}
}
public Delegate Delegate { get { return delegate_; } }
Delegate delegate_;
[Serializable]
class AnonymousClassWrapper : ISerializable
{
internal AnonymousClassWrapper(Type bclass, object bobject)
{
this.type = bclass;
this.obj = bobject;
}
internal AnonymousClassWrapper(SerializationInfo info, StreamingContext context)
{
Type classType = (Type)info.GetValue("classType", typeof(Type));
obj = Activator.CreateInstance(classType);
foreach (FieldInfo field in classType.GetFields())
{
//If the field is a delegate
if (typeof(Delegate).IsAssignableFrom(field.FieldType))
field.SetValue(obj,
((SerializeDelegate)info.GetValue
(field.Name, typeof(SerializeDelegate)))
.Delegate);
//If the field is an anonymous class
else if(!field.FieldType.IsSerializable)
field.SetValue(obj,
((AnonymousClassWrapper)info.GetValue
(field.Name, typeof(AnonymousClassWrapper)))
.obj);
//otherwise
else
field.SetValue(obj, info.GetValue(field.Name, field.FieldType));
}
}
void ISerializable.GetObjectData
(SerializationInfo info, StreamingContext context)
{
info.AddValue("classType", type);
foreach (FieldInfo field in type.GetFields())
{
//See corresponding comments above
if (typeof(Delegate).IsAssignableFrom(field.FieldType))
info.AddValue(field.Name, new SerializeDelegate
((Delegate)field.GetValue(obj)));
else if (!field.FieldType.IsSerializable)
info.AddValue(field.Name, new AnonymousClassWrapper
(field.FieldType, field.GetValue(obj)));
else
info.AddValue(field.Name, field.GetValue(obj));
}
}
public Type type;
public object obj;
}
}
历史
- 2009 年 2 月 12 日:初始发布