Silverlight 2.0 doesn't have an equivalent to the BinaryFormatter or NetDataContractSerializer. This makes some things quite challenging - in my case building CSLA Light. CSLA .NET requires high-fidelity serialization both for implementation of the Clone() operation and within the data portal.
I've been working on building a Silverlight-compatible equivalent to the BinaryFormatter/NDCS. It turns out to be quite hard due to the limitations of the Silverlight sandbox.
For example, Silverlight does have reflection, even against private fields. However, you can only get or set a private field with code inside the same class as the field declaration. You can't get/set a field from another object, or even from a base class or subclass. The reflection call must be in the same class!
At this point I have a prototype serializer that works in some limited scenarios. It is a starting point. Some aspects aren't ideal, but may just be the way they are to get around how Silverlight works. Still, the end result is relatively cool.
To use the serializer:
The MobileFormatter is far from complete. But it can serialize/deserialize fields of an object that contain primitive types (anything that works with Convert.ChangeType()). And it handles references to other serializable objects, both single objects and lists of serializable objects (if they implement IMobileObject or inherit from MobileList<T> ).
I'm pretty sure it can't handle arrays, nor can it handle any list type other than (effectively) List<T>. I'm not sure what it will do with enums or other types - just haven't gotten that far yet.
Here's a serializable object:
using System; using Csla.Serialization; namespace SilverlightApplication1 { [Serializable] public class Person : MobileObject { #region Serialization protected override object GetValue(System.Reflection.FieldInfo field) { if (field.DeclaringType == typeof(Person)) return field.GetValue(this); else return base.GetValue(field); } protected override void SetValue(System.Reflection.FieldInfo field, object value) { if (field.DeclaringType == typeof(Person)) field.SetValue(this, value); else base.SetValue(field, value); } #endregion public string Name { get; set; } [NonSerialized] private DateTime _birthdate; public DateTime BirthDate { get { return _birthDate; } set { _birthdate = value; } } } }
using System; using Csla.Serialization;
namespace SilverlightApplication1 { [Serializable] public class Person : MobileObject { #region Serialization
protected override object GetValue(System.Reflection.FieldInfo field) { if (field.DeclaringType == typeof(Person)) return field.GetValue(this); else return base.GetValue(field); }
protected override void SetValue(System.Reflection.FieldInfo field, object value) { if (field.DeclaringType == typeof(Person)) field.SetValue(this, value); else base.SetValue(field, value); }
#endregion
public string Name { get; set; }
[NonSerialized] private DateTime _birthdate; public DateTime BirthDate { get { return _birthDate; } set { _birthdate = value; } } } }
And here's how to serialize/deserialize the object:
var p = new Person(); var formatter = new Csla.Serialization.MobileFormatter(); var buffer = new System.IO.MemoryStream(); formatter.Serialize(buffer, p); buffer.Position = 0; var copyOfP = (Person)formatter.Deserialize(buffer);
Though it is unfortunate that every business class must implement GetValue() and SetValue(), I think that is a relatively small price to pay to get nearly the same capability as we have in .NET with the BinaryFormatter in terms of cloning objects, and more importantly in terms of serializing them across the network with full fidelity.
Powered by: newtelligence dasBlog 2.0.7226.0
Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.
© Copyright 2008, Rockford Lhotka
E-mail