在 C# 中序列化匿名委托 [英] Serializing anonymous delegates in C#

查看:53
本文介绍了在 C# 中序列化匿名委托的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试确定使用以下序列化代理来启用匿名函数/委托/lambda 的序列化可能会导致哪些问题.

I am trying to determine what issues could be caused by using the following serialization surrogate to enable serialization of anonymous functions/delegate/lambdas.

// 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 的修订之间保持不变.根据我对迭代器类似问题的研究,我相当肯定这是这种情况.

The main issue I can think of that might be a problem is that the anonymous class is an internal compiler detail and it's structure is not guaranteed to remain constant between revisions to the .NET Framework. I'm fairly certain this is the case based on my research into the similar problem with iterators.

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

I am investigating the serialization of anonymous functions. I was expecting this not to work, but found it did for some cases. As long as the lambda did *not& force the compiler to generate an anonymous class everything works fine.

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

A SerializationException is thrown if the compiler requires a generated class to implement the anonymous function. This is because the compiler generated class is not marked as serializable.

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.
        }
    }

清单 2

这类似于尝试序列化迭代器的问题,我在之前的搜索中找到了以下代码(参见 countingdemo) 使用清单 1 中的代码和 ISurrogateSelector,我能够成功地序列化和反序列化第二个失败的示例.

This is similar to the issue of trying to serialize iterators and I had found the following code in a previous search (see countingdemo) Using the code from Listing 1 and an ISurrogateSelector I was able to successfully serialize and deserialize the second failing example.

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

I have a system that is exposed via a web service. The system has a complex but small state (many objects, not a lot of properties per object). The state is saved in the ASP.NET Cache, but is also serialized to a BLOB in SQL in case of cache expiration. Some objects need to execute arbitrary "events" upon reaching some condition. Hence they have properties accepting Action/Func objects. Contrived example:

    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 ?不幸的是,微软已经确认他们可能会更改编译器详细信息(有一天),以一种可能会导致问题的方式.(例如,当您更新到新编译器时,您将无法反序列化您在旧(当前)编译器下保存的内容.)

Did you see this post that I wrote as a followup to the CountingDemo: http://dotnet.agilekiwi.com/blog/2007/12/update-on-persistent-iterators.html ? Unfortunately, Microsoft have confirmed that they probably will change the compiler details (one day), in a way that is likely to cause problems. (e.g. f/when you update to the new compiler, you won't be able to deserialise the stuff you saved under the old (current) compiler.)

这篇关于在 C# 中序列化匿名委托的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆