Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Persist an object that is not marked as serializable

Tags:

I need to persist an object that is not marked with the serializable attribute. The object is from a 3rd party library which I cannot change.

I need to store it in a persist place, like for example the file system, so the optimal solution would be to serialize the object to a file, but since it isn't marked as serializable, that is not a straight forward solution.

It's a pretty complex object, which also holds a collection of other objects.

Do you guys have any input on how to solve this? The code will never run in a production environment, so I'm ok with almost any solution and performance.

like image 291
lasseeskildsen Avatar asked Apr 07 '10 20:04

lasseeskildsen


People also ask

Is Java lang object serializable?

The reason the java. lang. Object didnt implement Serializable is because, what if you do NOT want to make certain fields as Serializable and you my mistake missed to add transient to that field, then will be a havoc. 3.

What is serializable in C#?

Serialization is the process of converting an object into a stream of bytes to store the object or transmit it to memory, a database, or a file. Its main purpose is to save the state of an object in order to be able to recreate it when needed.

How Java serialization works internally?

To serialize an object means to convert its state to a byte stream so that the byte stream can be reverted back into a copy of the object. A Java object is serializable if its class or any of its superclasses implements either the java. io. Serializable interface or its subinterface, java.

How many types of serialization are there in C#?

There are three types of serialization in . Net : Binary Serialization, SOAP Serialization and XML Serialization. Binary serialization is the process where you convert your . NET objects into byte stream.


2 Answers

XmlSerializer may be a useful first thing to try, if the types are public etc

If that fails, v2 of protobuf-net (in progress, you'd need to build from source, but I can help) works with unattributed objects, so ideal for types outside your control - you just need to tell it what to include (via a DSL). The v2 code isn't complete, but it covers most common scenarios, including collections etc (the incomplete work is mainly callbacks and enums).

like image 76
Marc Gravell Avatar answered Oct 07 '22 02:10

Marc Gravell


You could write a recursive method that would run down the object graph using reflection to persist the object... Putting it back could be much more difficult. Who knows if any of those objects are holding references to unmanaged or system resources. If i was to do anything this nuts, I would go for the .GetFields(...) method on the type.

Another idea...

If you are only doing this to speed up development why not wrap their clases with your own adapter classes. This would allow you to replace the third party libraries with your own simplifed mock classes and allow for better chance for replacement and reuse later.

Sick as it is... This was easier then I thought it would be. (While this works... please consider wrapping the third party classes.)

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 } }     } } 
like image 29
Matthew Whited Avatar answered Oct 07 '22 02:10

Matthew Whited