I am using Sterling DB in a WP7 app and trying to implement a custom serialiser for, hopefully, performance gains.
I'll provide an example (excuse all formatting, trying to compress it t开发者_高级运维o keep it small). Given a type that inherits List<string>:
public class TypedList : List<string>
{
public Guid ObjectId { get; set; }
public TypedList() { }
public TypedList(int count) : base(count) { }
}
And it's serialiser:
public class TypedListSerializer : Wintellect.Sterling.Serialization.BaseSerializer
{
public override bool CanSerialize(Type targetType)
{
return targetType.Equals(typeof(TypedList));
}
public override object Deserialize(Type type, BinaryReader reader)
{
int count = reader.ReadInt32();
var list = new TypedList(count);
for (int i = 0; i < count; i++)
list.Add(reader.ReadString());
return list;
}
public override void Serialize(object target, BinaryWriter writer)
{
var list = (TypedList)target;
writer.Write(list.Count);
foreach (string s in list)
writer.Write(s);
}
}
I register the serialiser with the engine:
_engine = new SterlingEngine();
_engine.SterlingDatabase.RegisterSerializer<TypedListSerializer>();
_engine.Activate();
Assuming a table of TypedList
types. Now when I try to save/load this type on the Sterling instance:
// _instance is a class that inherits BaseDatabaseInstance from the Sterling code.
_instance.Save<TypedList>(list);
_instance.Flush();
_instance.Load<TypedList>(g); // g is Guid.
It calls into CanSerialize
, but the Type
it is given is that of T
from List<T>
, the class I inherit from. If you change string
to int
, it tells me the type is an int
.
Has anyone else had this problem? Is this a Sterling issue or one with type information on generics?
Update: as per Marc's suggestion about inheritance, I amended my type to the following:
public class TypedList
{
public Guid ObjectId { get; set; }
public List<int> Items { get; set; }
public TypedList()
{
Items = new List<int>();
}
}
What the serializer appears to be doing is checking the properties of TypedList
instead of the type itself. I'm guessing this is now a fault with how I'm using Sterling. My table registration line looks like this:
protected override List<ITableDefinition> RegisterTables()
{
return new List<ITableDefinition>
{
CreateTableDefinition<TypedList, Guid>(l => l.ObjectId)
};
}
Just for what it's worth - Sterling expects to be in full control of "top level" entities so it can build the keys, indexes, and other parts that it needs to function. That is why it never calls the custom serializer for the top-level entity (the one you define to have indexes and keys). The custom serializers are meant for properties off of those tables. The fix above is correct because it now sees the list as a property rather than the top level "item" it is trying to serialize.
I'm not familiar with that serializer, but it is not uncommon for serializers to "take over" when it comes from lists - using an inbuilt mechanism for representing [n] items, but using the regular pipeline for each item in turn. I suspect (purely on a hunch) that this is what is happening here.
Note that as a consequence (and in common with a number of other serializers) it may be inadvisable to have values on the list itself (i.e. ObjectId
). I would usually use encapsulation rather than inheritance:
public class TypedList
{
public Guid ObjectId { get; set; }
private readonly List<string> items = new List<string>();
public List<string> Items { get { return items; } }
}
i.e. something that has the ObjectId and has a list, rather than something that has the ObjectId and is a list.
精彩评论