c# - 我可以在 .NET 4 中序列化 ExpandoObject 吗?

标签 c# .net serialization dynamic expandoobject

我正在尝试使用 System.Dynamic.ExpandoObject,这样我就可以在运行时动态创建属性。后来,我需要传递一个这个对象的实例,使用的机制需要序列化。

当然,当我尝试序列化我的动态对象时,我得到了异常:

System.Runtime.Serialization.SerializationException was unhandled.

Type 'System.Dynamic.ExpandoObject' in Assembly 'System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is not marked as serializable.

我可以序列化 ExpandoObject 吗?是否有另一种方法来创建可序列化的动态对象?也许使用 DynamicObject包装器?

我创建了一个非常简单的 Windows 窗体示例来重现错误:

using System;
using System.Windows.Forms;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Dynamic;

namespace DynamicTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {            
            dynamic dynamicContext = new ExpandoObject();
            dynamicContext.Greeting = "Hello";

            IFormatter formatter = new BinaryFormatter();
            Stream stream = new FileStream("MyFile.bin", FileMode.Create,
                                           FileAccess.Write, FileShare.None);
            formatter.Serialize(stream, dynamicContext);
            stream.Close();
        }
    }
}

最佳答案

我无法序列化 ExpandoObject,但我可以手动序列化 DynamicObject。因此,使用 DynamicObject 的 TryGetMember/TrySetMember 方法并实现 ISerializable,我可以解决真正序列化动态对象的问题。

我在我的简单测试应用中实现了以下内容:

using System;
using System.Windows.Forms;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Collections.Generic;
using System.Dynamic;
using System.Security.Permissions;

namespace DynamicTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {            
            dynamic dynamicContext = new DynamicContext();
            dynamicContext.Greeting = "Hello";
            this.Text = dynamicContext.Greeting;

            IFormatter formatter = new BinaryFormatter();
            Stream stream = new FileStream("MyFile.bin", FileMode.Create, FileAccess.Write, FileShare.None);
            formatter.Serialize(stream, dynamicContext);
            stream.Close();
        }
    }

    [Serializable]
    public class DynamicContext : DynamicObject, ISerializable
    {
        private Dictionary<string, object> dynamicContext = new Dictionary<string, object>();

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            return (dynamicContext.TryGetValue(binder.Name, out result));
        }

        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            dynamicContext.Add(binder.Name, value);
            return true;
        }

        [SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]
        public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            foreach (KeyValuePair<string, object> kvp in dynamicContext)
            {
                info.AddValue(kvp.Key, kvp.Value);
            }
        }

        public DynamicContext()
        {
        }

        protected DynamicContext(SerializationInfo info, StreamingContext context)
        {
            // TODO: validate inputs before deserializing. See http://msdn.microsoft.com/en-us/library/ty01x675(VS.80).aspx
            foreach (SerializationEntry entry in info)
            {
                dynamicContext.Add(entry.Name, entry.Value);
            }
        }

    }
}

Why does SerializationInfo not have TryGetValue methods?有缺失的拼图以保持简单。

关于c# - 我可以在 .NET 4 中序列化 ExpandoObject 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4853574/

相关文章:

c# - 如何在 C# 单元测试中显示控制台窗口?

c# - 当 SUIT 利用任务并行库时使用 Mocks 进行单元测试

c# - 从代码后面带参数调用 javascript 函数

perl - 在数据库上存储对象并检索它

c# - (_) => 做工作();下划线如何作为匿名委托(delegate)参数有效?

.net - DataTemplate 作为具有可定制绑定(bind)的资源

c# - 使用 Linq 从 C# 代码避免 SQL 注入(inject) MSSQL Server 的最佳方法?

c# - 在Windows 7下启动System.Diagnostics.Process时出现问题

c# - 在 WPF 中序列化 BitmapImage

c++ - 正确的类型转换以 boost 不同派生类的反序列化