dynamically - expandoobject c# example
¿Puedo serializar un ExpandoObject en.NET 4? (3)
No puedo serializar ExpandoObject, pero puedo serializar manualmente DynamicObject. Entonces, usando los métodos TryGetMember / TrySetMember de DynamicObject e implementando ISerializable, puedo resolver mi problema, que era realmente serializar un objeto dinámico.
Implementé lo siguiente en mi aplicación de prueba 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);
}
}
}
}
y ¿Por qué SerializationInfo no tiene métodos TryGetValue? tenía la pieza faltante del rompecabezas para mantenerlo simple.
Intento usar System.Dynamic.ExpandoObject
para poder crear propiedades dinámicamente en tiempo de ejecución. Más tarde, necesito pasar una instancia de este objeto y el mecanismo utilizado requiere serialización.
Por supuesto, cuando intento serializar mi objeto dinámico, obtengo la excepción:
System.Runtime.Serialization.SerializationException no fue manejado.
Escriba ''System.Dynamic.ExpandoObject'' en Assembly ''System.Core, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = b77a5c561934e089'' no está marcado como serializable.
¿Puedo serializar el ExpandoObject? ¿Hay algún otro enfoque para crear un objeto dinámico que sea serializable? ¿Quizás usando un contenedor DynamicObject ?
Creé un ejemplo muy simple de Windows Forms para duplicar el error:
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();
}
}
}
Tal vez sea un poco tarde para responder, pero utilizo jsonFx para serializar y deserializar expandoObjects y funciona muy bien:
publicación por entregas:
dim XMLwriter As New JsonFx.Xml.XmlWriter
dim serializedExpando as string =XMLwriter.Write(obj)
deserialización
dim XMLreader As New JsonFx.Xml.XmlReader
Dim obj As ExpandoObject = XMLreader.Read(Str)
ExpandoObject
implementa IDictionary<string, object>
, por ejemplo:
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();
}
}
Podrías escribir los contenidos del diccionario en un archivo, y luego crear un nuevo ExpandoObject a través de la deserialización, devolverlo a un diccionario y volver a escribir las propiedades?