c# - 在 C# 中序列化匿名委托(delegate)

标签 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, 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;
    }
}  

list 1 改编自 Counting Demo

我能想到的主要问题可能是匿名类是一个内部编译器细节,并且不能保证它的结构在 .NET Framework 的修订之间保持不变。根据我对迭代器的类似问题的研究,我相当确定情况就是如此。

背景

我正在研究匿名函数的序列化。我原以为这行不通,但发现在某些情况下确实如此。只要 lambda *不&强制编译器生成匿名类,一切正常。

如果编译器需要生成的类来实现匿名函数,则会抛出 SerializationException。这是因为编译器生成的类未标记为可序列化。

例子

namespace Example
{
    [Serializable]
    class Other
    {
        public int Value;
    }

    [Serializable]
    class Program
    {
        static void Main(string[] args)
        {
            MemoryStream m = new MemoryStream();
            BinaryFormatter f = new BinaryFormatter();

            // Example 1
            Func<int> succeeds = () => 5;
            f.Serialize(m, succeeds);

            // Example 2
            Other o = new Other();
            Func<int> fails = () => o.Value;
            f.Serialize(m, fails); // throws SerializationException - Type 'Example.Program+<>c__DisplayClass3' in Assembly 'Example, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.
        }
    }

list 2

这类似于尝试序列化 iterators 的问题,我在之前的搜索中找到了以下代码(请参阅 countingdemo)使用 list 1 和一个 ISurrogateSelector 我能够成功地序列化和反序列化第二个失败的例子。

目标

我有一个通过网络服务公开的系统。系统有一个复杂但很小的状态(很多对象,而不是每个对象的很多属性)。状态保存在 ASP.NET 缓存中,但也会在缓存过期时序列化为 SQL 中的 BLOB。有些对象需要在达到某些条件时执行任意“事件”。因此它们具有接受 Action/Func 对象的属性。人为的例子:

    class Command
    {
        public Command(Action action, Func<bool> condition);
    }

别处

    void DoSomethingWithThing(Thing thing)
    {
        state = Store.GetCurrentState();

        Command cmd = new Command(() => thing.Foo(), () => thing.IsReady())
        state.Add(cmd);

        Store.Save(state);
    }

最佳答案

你有没有看到我写的这篇文章作为 CountingDemo 的后续文章:http://dotnet.agilekiwi.com/blog/2007/12/update-on-persistent-iterators.html ?不幸的是,微软已经确认他们可能会(有一天)以一种可能导致问题的方式更改编译器细节。 (例如,f/当您更新到新编译器时,您将无法反序列化在旧(当前)编译器下保存的内容。)

关于c# - 在 C# 中序列化匿名委托(delegate),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/321827/

相关文章:

.net - 您最喜欢哪些适用于 .NET 和 Oracle 的 ORM 框架?

java - 用于将 java 对象树保存到数据库或文件的开源库

scala - 如何从graphx中的元组构建图并在之后标记节点?

c# - Linq 按不排序排序

c# - 如何在 C# 中从 RGB (565) 值绘制 2D 图像

WCF 服务内存泄漏

java - 为什么我的递归方法使我的程序抛出 InvalidClassException?

c# - 如何在 WPF 中将组合框绑定(bind)到其他项目的枚举?

c# - Environment.CurrentDirectory 设置为 system32;我如何确定在哪里?

exception - Nlog错误(消息,异常)忽略异常