2010-04-07 29 views
21

Tôi cần phải lưu giữ một đối tượng không được đánh dấu bằng thuộc tính tuần tự. Đối tượng là từ thư viện của bên thứ ba mà tôi không thể thay đổi.Tiếp tục tồn tại một đối tượng không được đánh dấu là serializable

Tôi cần lưu trữ ở nơi kiên trì, ví dụ như hệ thống tệp, vì vậy giải pháp tối ưu sẽ là sắp xếp thứ tự đối tượng vào tệp, nhưng vì nó không được đánh dấu là có thể tuần tự hóa được. giải pháp chuyển tiếp.

Đó là một đối tượng khá phức tạp, cũng chứa một bộ sưu tập các đối tượng khác.

Các bạn có đầu vào nào về cách giải quyết vấn đề này không? Các mã sẽ không bao giờ chạy trong một môi trường sản xuất, vì vậy tôi ok với hầu như bất kỳ giải pháp và hiệu suất.

+12

nổi tiếng những lời cuối cùng ... 'Mã sẽ không bao giờ chạy trong một environment' sản xuất: OP –

+0

@Matthew: Yeah, right :-) +1 – driis

+0

Heh, tôi biết :) Nó chỉ để tăng tốc độ thời gian ấm lên trong dev, do đó, nó không có ý nghĩa nhiều bất cứ nơi nào khác. – lasseeskildsen

Trả lời

9

XmlSerializer có thể là một điều hữu ích đầu tiên để thử, nếu các loại công khai, v.v.

Nếu không thành công, v2 của protobuf-net (đang tiến hành, bạn sẽ muốn d để xây dựng từ nguồn, nhưng tôi có thể giúp) làm việc với các đối tượng không được phân bổ, vì vậy lý tưởng cho các loại ngoài tầm kiểm soát của bạn - bạn chỉ cần nói với nó những gì cần đưa vào (thông qua DSL). Mã v2 không hoàn chỉnh, nhưng nó bao gồm hầu hết các kịch bản phổ biến, bao gồm các bộ sưu tập vv (công việc không hoàn chỉnh chủ yếu là các cuộc gọi lại và enums).

+0

protobuf-net trông khá đẹp. Liệu nó đòi hỏi các nhà xây dựng parameterless? – lasseeskildsen

+0

@lasseeskildsen - tại thời điểm hiện tại, vâng - nhưng kể từ khi tôi sở hữu nó, tôi chắc chắn rằng tôi có thể thêm phương pháp WCF (không gọi bất kỳ ctor). Nó sẽ chỉ mất vài phút (nó chỉ là một lời gọi tới 'FormatterServices.GetUninitializedObject'). –

+0

Nếu bạn có một ví dụ về API của bên thứ ba, tôi có thể giả mạo một ví dụ v2. –

2

Tôi không biết liệu nó có quá mức cần thiết cho việc sử dụng của bạn hay không, nhưng gần đây tôi đã chơi với db4o. Nó sẽ tồn tại bất kỳ đối tượng nào, chỉ cần gọi IObjectContainer.Store (đối tượng), và nó có trọng lượng nhẹ và dựa trên tệp. Không yêu cầu bất kỳ cài đặt nào.

Tôi chưa gặp bất kỳ sự cố nào với nó.

3

Đây là một cách để bạn có thể làm điều đó:

http://www.codeproject.com/KB/dotnet/Surrogate_Serialization.aspx

ở đây là liên kết MSDN hiển thị nó:

http://msdn.microsoft.com/en-us/magazine/cc188950.aspx

+0

Các liên kết không hoạt động nữa. Bài viết đầu tiên: [link] (https: //web.archive.org/web/20101213020136/http: //www.codeproject.com/kb/dotnet/Surrogate_Serialization.aspx) Bài viết thứ hai: [link] (https://web.archive.org/web/20141231105711/http://msdn .microsoft.com/vi-us/magazine/cc188950.aspx) – milosa

5

Bạn có thể viết một phương pháp đệ quy sẽ chạy xuống biểu đồ đối tượng bằng cách sử dụng phản chiếu để tiếp tục đối tượng ... Đặt lại có thể khó khăn hơn nhiều. Ai biết được liệu có bất kỳ đối tượng nào trong số đó đang giữ tham chiếu đến tài nguyên không được quản lý hay hệ thống không. Nếu tôi đã làm bất cứ điều gì hạt này, tôi sẽ đi cho các phương pháp .GetFields(...) trên loại.

ý tưởng khác ...

Nếu bạn chỉ làm điều này để tăng tốc độ phát triển tại sao không quấn clases của họ với các lớp học chuyển đổi của riêng bạn. Điều này sẽ cho phép bạn thay thế các thư viện của bên thứ ba bằng các lớp mô hình đơn giản của riêng bạn và cho phép cơ hội thay thế và sử dụng lại sau này tốt hơn.

Bệnh vì nó là ... Điều này dễ dàng hơn sau đó tôi nghĩ là như vậy. (Trong khi làm việc này ... xin vui lòng xem xét gói các lớp bên thứ ba.)

public static class Tools 
{ 
    public static XElement AsXml(this object input) 
    { 
     return input.AsXml(string.Empty); 
    } 
    public static XElement AsXml(this object input, string name) 
    { 
     if (string.IsNullOrEmpty(name)) 
      name = input.GetType().Name; 

     var xname = XmlConvert.EncodeName(name); 

     if (input == null) 
      return new XElement(xname); 

     if (input is string || input is int || input is float /* others */) 
      return new XElement(xname, input); 

     var type = input.GetType(); 
     var fields = type.GetFields(BindingFlags.Instance | 
            BindingFlags.NonPublic) 
         .Union(type.GetFields(BindingFlags.Instance | 
               BindingFlags.Public)); 

     var elems = fields.Select(f => f.GetValue(input) 
             .AsXml(f.Name)); 

     return new XElement(xname, elems); 
    } 
    public static void ToObject(this XElement input, object result) 
    { 
     if (input == null || result == null) 
      throw new ArgumentNullException(); 

     var type = result.GetType(); 
     var fields = type.GetFields(BindingFlags.Instance | 
            BindingFlags.NonPublic) 
         .Union(type.GetFields(BindingFlags.Instance | 
               BindingFlags.Public)); 

     var values = from elm in input.Elements() 
        let name = XmlConvert.DecodeName(elm.Name.LocalName) 
        join field in fields on name equals field.Name 
        let backType = field.FieldType 
        let val = elm.Value 
        let parsed = backType.AsValue(val, elm) 
        select new 
        { 
         field, 
         parsed 
        }; 

     foreach (var item in values) 
      item.field.SetValue(result, item.parsed);    
    } 

    public static object AsValue(this Type backType, 
             string val, 
             XElement elm) 
    { 
     if (backType == typeof(string)) 
      return (object)val; 
     if (backType == typeof(int)) 
      return (object)int.Parse(val); 
     if (backType == typeof(float)) 
      return (float)int.Parse(val); 

     object ret = FormatterServices.GetUninitializedObject(backType); 
     elm.ToObject(ret); 
     return ret; 
    } 
} 
public class Program 
{ 
    public static void Main(string[] args) 
    { 
     var obj = new { Matt = "hi", Other = new { ID = 1 } }; 
     var other = new { Matt = "zzz", Other = new { ID = 5 } }; 
     var ret = obj.AsXml(); 
     ret.ToObject(other); 
     Console.WriteLine(obj); //{ Matt = hi, Other = { ID = 1 } } 
     Console.WriteLine(other); //{ Matt = hi, Other = { ID = 1 } } 
    } 
} 
+0

+1 Gói là ý tưởng tuyệt vời trong một kịch bản như thế này. – Filburt

+0

Vâng, tôi vừa thử xây dựng một giải pháp nhanh để duy trì và khôi phục các đối tượng dựa trên các giá trị riêng tư. Kiên trì là khá dễ dàng; vấn đề đi kèm với việc khôi phục chúng. Nếu bạn không có quyền truy cập vào một constructor ít hơn thì nó có thể là không thể. –

+0

Tôi không chịu trách nhiệm nếu đoạn mã trên làm cho thế giới phát nổ và tất cả sự sống trong vũ trụ đến một kết thúc đột ngột –

0
///Here OBJECT is Class name and Object_to_write is instance 
XmlSerializer serializer = new XmlSerializer(typeof(OBJECT)); 
using (TextWriter writer = new StreamWriter(@"C:\Xml.xml")) 
{ 
    serializer.Serialize(writer, OBJECT_to_Write); 
} 
+0

> Đối tượng là từ thư viện của bên thứ 3 mà tôi không thể thay đổi. XmlSerializer có thể ném InvalidOprationException: [đối tượng] không thể được tuần tự hóa bởi vì nó không có một hàm tạo tham số. –

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