Posts Tagged C#

SilverlightSerializer Version 2


SilverlightSerializer version 2

Well, I know it’s been a long wait and I’ve been promising the new version of SilverlightSerializer for months, but it’s finally here, extracted from my core project and working standalone.

This new version of the serializer is a major rewrite – with 2 goals in mind:

1. Performance

Serialization performance is 61% faster (my test harness serializes 100,000 objects in 1.03 seconds compared to 1.72)
Deserialization performance is 27% faster (my test hardness deserializes 100,000 objects in 1.61 seconds compared to 2.04)

These performance gains are on large object graphs containing multiple instances of the same types – it would nominally be slightly slower on small graphs or graphs that contain only one copy of each object – but of course that’s very unlikely in the real world.

2. Extensibility

The new version of SilverlightSerializer abstracts the storage methods behind a new interface, IStorage.  There’s a complete implementation of a BinarySerializer that is compatible with the old version of SilverlightSerializer, but you could add your own.  Alterian has built versions that store data in XML and SQL Server tables.  This means one standard semantic serialization layer can be used with pluggable storage types to put the information where you need it for the application at hand.

That said, writing an IStorage is fairly involved process and I’ll write a post or a page on it if people want me to.

In addition the serializer now handles arrays and enums far better than before and hopefully should avoid the dreaded MissingMethod exception by providing a more developer friendly exception and message while offering the opportunity to construct classes without a parameterless constructor using a new CreateType event that will help some avoid the need to write custom serializers.

You can find the version 2 source code here.  In response to a couple of requests, the project is also accessible on GitHub, see the link at the top of the SilverlightSerializer page.

Why is it faster?

So read on if you’d like to know why it’s faster!

SilverlightSerializer is a reflection based serializer.  It examines an object to identify the available properties and fields. As anyone who is familiar with .NET will know, reflection isn’t exactly the fastest thing in the world.  SS v1 did its level best to cache everything possible, but it still relied on reflection to write and read properties and fields from the underlying objects.  This is why SS didn’t perform as well as the inbuilt serializers in .NET.

Now reflection in this case is a hard thing to get around, I don’t know the types in advance and I have no interest in getting the developer to have to write a custom serialization class for each of their types.

The answer to this performance challenge came from using generic classes and using .NET to construct a new generic class on the fly for each property of each class being serialized.  The generic class accesses the native property access functions directly, rather than have to use reflection.  Fields have to be handled slightly differently, with a reflection function, but at least it’s no slower than the previous method.

First let’s start with the base class that is used for all of the generic classes, it’s called GetSet.


public abstract class GetSet
{
public PropertyInfo Info;
public string Name;
public FieldInfo FieldInfo;
public object Vanilla;
public bool CollectionType;
public abstract object Get(object item);
public abstract void Set(object item, object value);

}

From this base class I create a definition of a generic class, called GetSetGeneric.  This class creates Get and Set delegates using the class parameters, these delegates then map to the functions that will be exposed by the property getters and setters on the target class (neat huh).  This happens only once per type/property combination and the resulting code is the same speed as writing a function to get the value.

public class GetSetGeneric<T, TR> : GetSet
{
public delegate TR GetValue(T obj);
public delegate void SetValue(T obj, TR value);
private readonly GetValue _get;
private readonly SetValue _set;

public GetSetGeneric(PropertyInfo info)
{
MethodInfo getMethod;
MethodInfo setMethod = null;
Name = info.Name;
Info = info;
CollectionType = Info.PropertyType.GetInterface("IEnumerable", true) != null;
getMethod = info.GetGetMethod();
setMethod = info.GetSetMethod();
_get = (GetValue)Delegate.CreateDelegate(typeof(GetValue), getMethod);
if (setMethod != null) _set = (SetValue)Delegate.CreateDelegate(typeof(SetValue), setMethod);
}

public GetSetGeneric(FieldInfo info)
{
MethodInfo getMethod;
MethodInfo setMethod = null;
Name = info.Name;
FieldInfo = info;
_get = new GetValue(GetFieldValue);
_set = new SetValue(SetFieldValue);
CollectionType = FieldInfo.FieldType.GetInterface("IEnumerable", true) != null;
return;
}

public GetSetGeneric(string name)
{
Name = name;
MethodInfo getMethod;
MethodInfo setMethod= null;
var t = typeof(T);
var p = t.GetProperty(name);
if (p == null)
{
FieldInfo = typeof(T).GetField(Name);
_get = new GetValue(GetFieldValue);
_set = new SetValue(SetFieldValue);
CollectionType = FieldInfo.FieldType.GetInterface("IEnumerable", true) != null;
return;
}
Info = p;
CollectionType = Info.PropertyType.GetInterface("IEnumerable", true) != null;
getMethod = p.GetGetMethod();
setMethod = p.GetSetMethod();
_get = (GetValue)Delegate.CreateDelegate(typeof(GetValue), getMethod);
if(setMethod != null) _set = (SetValue)Delegate.CreateDelegate(typeof(SetValue), setMethod);
}

private TR GetFieldValue(T obj)
{
return (TR)FieldInfo.GetValue(obj);
}

private void SetFieldValue(T obj, TR value)
{
FieldInfo.SetValue(obj, value);
}

public override object Get(object item)
{
return _get((T)item);
}

public override void Set(object item, object value)
{
_set((T)item, (TR)value);
}
}

Once that’s done it’s just a matter of creating the generic classes. Deserialization does this one property at a time form the input stream:

entryConfiguration = new EntryConfiguration();

var pi = entry.OwningType.GetProperty(entry.Name);
if (pi != null)
{
entryConfiguration.Type = pi.PropertyType;
var gs = typeof(GetSetGeneric<,>);
var tp = gs.MakeGenericType(new Type[] { entry.OwningType, pi.PropertyType });
entryConfiguration.Setter = (GetSet)Activator.CreateInstance(tp, new object[] { pi });
}
else
{
var fi = entry.OwningType.GetField(entry.Name);
if (fi != null)
{
entryConfiguration.Type = fi.FieldType;
var gs = typeof(GetSetGeneric<,>);
var tp = gs.MakeGenericType(new Type[] { entry.OwningType, fi.FieldType });
entryConfiguration.Setter = (GetSet)Activator.CreateInstance(tp, new object[] { fi });
}
}

Here you can see I get either the property or the field information, use the type of the containing class and the property in a call to MakeGenericType to construct the correct class, then create an instance of that class that can be used to get and set properties on the object.
Serialization works by creating a list of getters and setters for every sensible property on the object, in SilverlightSerializer that creates a few different flavours depending on whether you are using Checksums etc. If you want to see how I do that, have a look at the GetWriteableAttributes class and the GetAccessors() function.

, , , , , , , , , ,

10 Comments

Silverlight Flip Control – page flipping without the performance problems



Download

A while ago I was blogging about the flip control that I had written for Silverlight. My first attempt at this used basic transitions only to show two sides of a page, but I found this slowed down dramatically when the contents of each side were complex.  The answer was to take an image of the contents of each side at the moment of the flip occuring and animate that instead, in this way it’s always smooth no matter how many controls are being used.

I’m posting the code for the control here.  As usual feel free to use or modify it in any way you like, I’d appreciate any really interesting upgrades be sent back to me so I can include them here.  There’s a sample project and web site in the ZIP file too.

The flip control is pretty straight forward.  It has two sides called Page1 and Page2.  The property used to flip over the control is Page2Visible, which is a bool.  There’s a PageChanged event that fires if you need the notificaton.  There are also advanced properties for horizontal and vertical alignment separate for each side (Side1VerticalAlignment etc).

If you are looking through the code then it’s CreateImages that does most of the hard work.  This routine takes an image of each of the pages and swops those for the real content during the flip.  The images are reset when the Visual State Manager says the transition is complete.

 

, , , , , ,

9 Comments