我试图使用System.Dynamic.ExpandoObject,以便在运行时动态创建属性。稍后,我需要传递这个对象的一个实例,所使用的机制需要序列化。
当然,当我试图序列化我的动态对象时,我得到了异常:
System.Runtime.Serialization.SerializationException
未被处理。
程序集'System.Dynamic.ExpandoObject‘中的'System.Core,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089’类型不能标记为可串行化。
我可以序列化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();
}
}
}发布于 2011-01-31 23:29:40
我不能序列化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?有一个缺失的拼图。
发布于 2011-01-31 16:59:39
ExpandoObject实现IDictionary<string, object>,例如:
class Test
{
static void Main()
{
dynamic e = new ExpandoObject();
e.Name = "Hello";
IDictionary<string, object> dict = (IDictionary<string, object>)e;
foreach (var key in dict.Keys)
{
Console.WriteLine(key);
}
dict.Add("Test", "Something");
Console.WriteLine(e.Test);
Console.ReadKey();
}
}您可以将字典的内容写入文件,然后通过反序列化创建一个新的ExpandoObject,将其转换回字典并将属性写回?
发布于 2011-03-27 12:02:47
回答可能有点晚,但我使用jsonFx来序列化和反序列化expandoObjects,它运行得很好:
序列化:
dim XMLwriter As New JsonFx.Xml.XmlWriter
dim serializedExpando as string =XMLwriter.Write(obj)反序列化
dim XMLreader As New JsonFx.Xml.XmlReader
Dim obj As ExpandoObject = XMLreader.Read(Str)https://stackoverflow.com/questions/4853574
复制相似问题