Puis - je sérialiser un objet ExpandoObject in.NET 4?
j'essaie d'utiliser un System.Dynamic.ExpandoObject
pour créer dynamiquement des propriétés à l'exécution. Plus tard, je dois passer une instance de cet objet et le mécanisme utilisé nécessite une sérialisation.
bien sûr, quand j'essaie de sérialiser mon objet dynamique, j'obtiens l'exception:
du Système.Runtime.Sérialisation.SerializationException n'a pas été manipulée.
Type 'Système.Dynamique.ExpandoObject' en Assemblée de "Système".Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken = b77a5c561934e089' n'est pas marqué comme serialisable.
puis-je sérialiser L'objet Expando? Est-il une autre approche pour la création d'un objet dynamique est sérialisable? Peut-être en utilisant un DynamicObject wrapper?
j'ai créé un exemple de formulaires Windows très simple pour dupliquer l'erreur:
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();
}
}
}
3 réponses
Je ne peux pas sérialiser ExpandoObject, mais je peux sérialiser manuellement DynamicObject. Ainsi, en utilisant les méthodes TryGetMember/TrySetMember de DynamicObject et implementing ISerializable, je peux résoudre mon problème qui était vraiment de sérialiser un objet dynamique.
j'ai implémenté ce qui suit dans mon application de test simple:
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);
}
}
}
}
et Pourquoi ne SerializationInfo pas TryGetValue méthodes? avait la pièce manquante garder les choses simples.
ExpandoObject
instruments IDictionary<string, object>
, p.ex.:
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();
}
}
vous pourriez écrire le contenu du dictionnaire à un fichier, puis créer un nouveau ExpandoObject par la deserialisation, le jeter à nouveau à un dictionnaire et écrire les propriétés de nouveau dans?
peut-être un peu tard pour répondre, mais j'utilise jsonFx pour sérialiser et desérialiser expandoObjects et cela fonctionne très bien:
sérialisation:
dim XMLwriter As New JsonFx.Xml.XmlWriter
dim serializedExpando as string =XMLwriter.Write(obj)
deserialisation
dim XMLreader As New JsonFx.Xml.XmlReader
Dim obj As ExpandoObject = XMLreader.Read(Str)