C# 在C中序列化匿名委托#
我试图确定使用以下序列化代理来启用匿名函数/delegate/lambda的序列化可能会导致哪些问题C# 在C中序列化匿名委托#,c#,.net-3.5,serialization,C#,.net 3.5,Serialization,我试图确定使用以下序列化代理来启用匿名函数/delegate/lambda的序列化可能会导致哪些问题 // see http://msdn.microsoft.com/msdnmag/issues/02/09/net/#S3 class NonSerializableSurrogate : ISerializationSurrogate { public void GetObjectData(object obj, SerializationInfo info, StreamingCon
// see http://msdn.microsoft.com/msdnmag/issues/02/09/net/#S3
class NonSerializableSurrogate : ISerializationSurrogate
{
public void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
{
foreach (FieldInfo f in obj.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
info.AddValue(f.Name, f.GetValue(obj));
}
public object SetObjectData(object obj, SerializationInfo info, StreamingContext context,
ISurrogateSelector selector)
{
foreach (FieldInfo f in obj.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
f.SetValue(obj, info.GetValue(f.Name, f.FieldType));
return obj;
}
}
清单1改编自
我能想到的主要问题可能是,匿名类是一个内部编译器细节,它的结构不能保证在.NET Framework的修订之间保持不变。基于我对迭代器的类似问题的研究,我相当肯定这是一种情况
背景
我正在调查匿名函数的序列化。我原以为这不管用,但发现在某些情况下管用了。只要lambda没有强制编译器生成一个匿名类,一切都正常
如果编译器需要生成的类来实现匿名函数,则会引发SerializationException。这是因为编译器生成的类未标记为可序列化
例子
序列化委托的整个想法是非常危险的。现在,表达式可能有意义,但即使这样也很难表达——尽管动态LINQ示例在某种程度上允许基于文本的表达式形式 对于序列化委托,您到底想做什么?我真的不认为这是个好主意 有些对象需要执行任意“事件”,达到某种条件 这些事件到底有多武断?它们是否可以计数、分配ID并映射到引用
public class Command<T> where T : ISerializable
{
T _target;
int _actionId;
int _conditionId;
public Command<T>(T Target, int ActionId, int ConditionId)
{
_target = Target;
_actionId = ActionId;
_conditionId = ConditionId;
}
public bool FireRule()
{
Func<T, bool> theCondition = conditionMap.LookupCondition<T>(_conditionId)
Action<T> theAction = actionMap.LookupAction<T>(_actionId);
if (theCondition(_target))
{
theAction(_target);
return true;
}
return false;
}
}
公共类命令,其中T:ISerializable
{
T_目标;
int_actionId;
int_conditionId;
公共命令(T目标、int ActionId、int ConditionId)
{
_目标=目标;
_actionId=actionId;
_条件ID=条件ID;
}
公共图书馆防火规则()
{
Func theCondition=conditionMap.LookupCondition(_conditionId)
Action theAction=actionMap.LookupAction(\u actionId);
如果(条件(_目标))
{
行动(_目标);
返回true;
}
返回false;
}
}
函数映射将阻止我在操作/条件中使用本地状态。解决这个问题的唯一方法是为每个需要附加状态的函数创建一个类
这就是C#编译器使用匿名函数自动为我做的事情。我的问题是这些编译器类的序列化
Other o = FromSomeWhere();
Thing t = OtherPlace();
target.OnWhatever = () => t.DoFoo() + o.DoBar();
target.Save();c
尝试序列化将失败。由于此状态是本地状态,因此在尝试设置映射时会出现问题。相反,我必须声明如下内容:
[Serializable]
abstract class Command<T>
{
public abstract T Run();
}
class DoFooBar : Command<int>
{
public Other Other { get; set; }
public Thing Thing { get; set; }
public override int Run()
{
return Thing.DoFoo() + Other.DoBar();
}
}
DoFooBar cmd = new DoFooBar();
cmd.Other = FromSomewhere();
cmd.Thing = OtherPlace();
target.OnWhatever = cmd.Run;
target.Save();
本质上,这意味着手动执行C#编译器为我自动执行的操作
由于此状态是本地状态,因此在尝试设置映射时会出现问题
对于序列化,本地州不会出现完全相同的问题吗
假设编译器和框架允许这样做:
Other o = FromSomeWhere();
Thing t = OtherPlace();
target.OnWhatever = () => t.DoFoo() + o.DoBar();
target.Save();
我想t和o也必须序列化。方法没有状态,实例有
稍后,反序列化目标。你没有新的t和o的副本吗?这些副本不会与原始t和o的任何更改不同步吗
另外:您的手动示例不能这样称呼吗
Other o = FromSomeWhere();
Thing t = OtherPlace();
target.OnWhatever = new DoFooBar() {Other = o, Thing = t} .Run;
target.Save();
你看到我写的这篇文章了吗?它是作为CountingDemo的后续内容:?不幸的是,微软已经确认,他们可能会(某一天)更改编译器的详细信息,这可能会导致问题。(例如,当您更新到新的编译器时,您将无法反序列化您在旧(当前)编译器下保存的内容。)我对此不是100%,但我相信,如果您希望将委托或某些代码“保存”到数据库中,并且可以相当动态,您需要做的是创建一个表达式,然后可以将表达式编译成Func
我编辑了我的问题,添加了一个目标部分。我也有一种普遍的“感觉”,这是有风险的,但没有很多具体的理由来解释为什么这是有风险的。我写下了我关于使用行动/条件图的问题。投票支持你的答案,因为它至少提供了一种选择。我希望“t”和“o”被序列化。当状态被反序列化(从数据库中)时,旧对象将消失,不再存在于内存中,因此冲突不是问题。我猜这基本上就是我的答案。必须注意编译器的更改,这样我才不会丢失序列化数据。+1他们确实更改了它,我们被它咬了一口。我把这个答案贴在上面:Other o=new Other();表达式失败=()=>o.值;f、 序列化(m,失败);//再次抛出序列化异常!
DoFooBar cmd = new DoFooBar();
cmd.Other = FromSomewhere();
cmd.Thing = OtherPlace();
target.OnWhatever = cmd.Run;
target.Save();
Other o = FromSomeWhere();
Thing t = OtherPlace();
target.OnWhatever = () => t.DoFoo() + o.DoBar();
target.Save();
Other o = FromSomeWhere();
Thing t = OtherPlace();
target.OnWhatever = new DoFooBar() {Other = o, Thing = t} .Run;
target.Save();