2011-01-31 21 views
27

Tôi đang cố gắng sử dụng System.Dynamic.ExpandoObject để tôi có thể tạo thuộc tính động trong thời gian chạy. Sau đó, tôi cần phải vượt qua một thể hiện của đối tượng này và cơ chế được sử dụng yêu cầu serialization.Tôi có thể tuần tự hóa ExpandoObject trong .NET 4 không?

Tất nhiên, khi tôi cố gắng để serialize đối tượng năng động của tôi, tôi nhận được ngoại lệ:

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.

Tôi có thể sắp đặt từng ExpandoObject? Có cách nào khác để tạo một đối tượng động có thể tuần tự hóa được không? Có lẽ sử dụng một wrapper DynamicObject?

tôi đã tạo ra một Windows rất đơn giản Forms ví dụ để lặp lại trong các lỗi:

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(); 
     } 
    } 
} 
+1

ngắn thực hiện một hướng dẫn serialization thường xuyên, tôi nghiêng để nói rằng nếu nó không được đánh dấu 'Serializable' sau đó, không, khá đơn giản. –

Trả lời

20

Tôi không thể tuần tự hóa ExpandoObject, nhưng tôi có thể tuần tự hóa DynamicObject theo cách thủ công. Vì vậy, bằng cách sử dụng các phương pháp TryGetMember/TrySetMember của DynamicObject và triển khai thực hiện ISerializable, tôi có thể giải quyết vấn đề của tôi mà thực sự là sắp xếp một đối tượng động.

tôi đã thực hiện những điều sau đây trong ứng dụng thử nghiệm đơn giản của tôi:

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ó mảnh ghép còn thiếu để giữ cho nó đơn giản.

+3

Đã có một số nghi ngờ về việc trả lời câu hỏi của riêng tôi, nhưng có vẻ như được khuyến khích: http://meta.stackexchange.com/questions/9933/is-there-a-convention-for-accepting-my-own-answer-to -my-own-question –

9

ExpandoObject thực hiện IDictionary<string, object>, ví dụ:

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(); 
    } 
} 

Bạn có thể viết nội dung của từ điển vào một tập tin , và sau đó tạo ExpandoObject mới thông qua deserialisation, đưa nó trở lại một từ điển và viết các thuộc tính trở lại?

+0

Nếu đầu ra phải ở dạng XML thì không thể được tuần tự hóa 'IDictionary <,> 'với [XmlSerializer] (http://msdn.microsoft.com/EN-US/library/swxzdhc0.aspx) nhưng nó có thể được tuần tự hóa [DataContractSerializer] (http://msdn.microsoft.com/EN-US/library/ms405768.aspx) mặc dù đầu ra quá dài. Cá nhân tôi nghĩ rằng JsonFx được đề cập trong câu trả lời khác làm công việc tốt hơn serializing 'ExpandoObject'. – Mike

8

Có lẽ hơi muộn để trả lời nhưng tôi sử dụng jsonFx serialize và deserialize expandoObjects và nó hoạt động rất tốt:

serialization:

dim XMLwriter As New JsonFx.Xml.XmlWriter 
dim serializedExpando as string =XMLwriter.Write(obj) 

deserialization

dim XMLreader As New JsonFx.Xml.XmlReader 
Dim obj As ExpandoObject = XMLreader.Read(Str) 
+3

Đẹp. JsonWriter vừa cứu tôi rất nhiều thời gian! Đây là Git cho JsonFx nếu ai đó cần nó: https://github.com/jsonfx/jsonfx –

+1

tôi đã thử điều này. Nó hoạt động hoàn hảo để tuần tự hóa đối tượng động, nhưng việc deserialization cho thấy một ngoại lệ: Tên thuộc tính dự kiến ​​đối tượng hoặc kết thúc đối tượng (Object Begin). – sharmakeshav

+0

Sử dụng JsonReader và Writer thay vì Xml để khắc phục ngoại lệ trên :) – faztp12

Các vấn đề liên quan