如何序列化对象,其中对象具有从操作创建的委托
本文关键字:对象 操作 创建 序列化 | 更新日期: 2023-09-27 17:55:13
如何序列化对象具有从Action
创建的Delegate
的对象,以便我可以反序列化对象并且Delegate
仍在订阅?
这是类代码:
[Serializable]
public class TestClass
{
public event EventHandler<EventArgs> refresh;
public void AddHandlerForAction()
{
var methodInfo = this.GetType().GetMethod("RefreshMethodNoParamaters");
Action action = (Action)Delegate.CreateDelegate(typeof(Action), this, methodInfo);
var eventInfo = this.GetType().GetEvent("refresh");
var handlerType = eventInfo.EventHandlerType;
var eventParams = handlerType.GetMethod("Invoke").GetParameters();
var parameters = eventParams.Select(p => Expression.Parameter(p.ParameterType, "x"));
var body = Expression.Call(Expression.Constant(action), action.GetType().GetMethod("Invoke"));
var lambda = Expression.Lambda(body, parameters.ToArray());
Delegate d = Delegate.CreateDelegate(handlerType, lambda.Compile(), "Invoke", false);
eventInfo.AddEventHandler(this, d);
}
public virtual object Clone()
{
Type type = this.GetType();
if (!type.IsSerializable)
{
throw new ArgumentException("The type must be serializable.", "source");
}
if (Object.ReferenceEquals(this, null))
{
return this.GetType().GetMethod("GetDefaultGeneric").MakeGenericMethod(type).Invoke(this, null);
}
using (MemoryStream stream = new MemoryStream())
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, this);
stream.Position = 0;
var clone = Convert.ChangeType(formatter.Deserialize(stream), type);
return clone;
}
}
public void RaiseEvent()
{
EventHandler<EventArgs> eventHandler = refresh;
if (eventHandler != null)
{
eventHandler(this, new EventArgs());
}
}
public void RefreshMethodNoParamaters()
{
}
}
下面是执行异常的代码:
var testClass = new TestClass();
testClass.AddHandlerForAction();
testClass.RaiseEvent();
var clone = testClass.Clone();
异常发生在以下代码行中:
formatter.Serialize(stream, this);
以下是例外:
类型的未处理异常 "System.Runtime.Serialization.SerializationException" 发生在 姆科利布.dll
其他信息:无法通过非托管序列化委托 函数指针、动态方法或委托外部的方法 创建者程序集。
代码的目的是订阅一个Event
,其中引发Event
时调用的方法没有参数。
如果您只想序列化该类,则可以使用 [NonSerialized]
属性。但是您需要使用属性目标(字段):
[field: NonSerialized]
public event EventHandler<EventArgs> refresh;
以下是有关属性规范的更多信息
编辑:
如果需要保留附加的事件(这将适用于您的示例,但不适用于长期存储),则可以在克隆函数中填充事件处理程序:
public virtual object Clone()
{
//...
var clone = Convert.ChangeType(formatter.Deserialize(stream), type);
(clone as TestClass).refresh = this.refresh;
return clone;
}
但就我的喜好而言,这是一种非常笨拙的方式......