我使用ServiceStack.OrmLite将数据保存在SQLite
数据库中,到目前为止对此非常满意。
但是,我的许多对象都具有复杂类型的属性,我不希望使用JSV
进行序列化。
我需要能够指定应该用于在数据库中存储属性的自定义序列化/反序列化(作为字符串)。在db4o
世界中,这相当于使用IObjectConstructor
提供的翻译功能。
无法正确序列化和反序列化的复杂类型的一个很好的例子是NodaTime类型,即使它们可以很容易地映射到字符串(我已经拥有了db4o
使用的序列化/反序列化函数)。 / p>
实现这一目标的最简单方法是什么?包装器不是很方便,因为我必须为包含这种复杂类型属性的每种类型编写和维护一个。
答案 0 :(得分:6)
对于那些可能对我正在使用Orclite实现自定义序列化的包装器模式感兴趣的人(也可以与其他ORM一起使用),这里有一个简单的工作示例NodaTime
类型,否则不能正确序列化:
public class BusinessObject {
public class Poco {
public readonly BusinessObject BusinessObject;
public Poco(BusinessObject businessObject) {
this.BusinessObject = businessObject;
}
public Poco() {
this.BusinessObject = new BusinessObject();
}
public string Id {
get { return this.BusinessObject.Id; }
set { this.BusinessObject.Id = value; }
}
public decimal Amount {
get { return this.BusinessObject.Amount; }
set { this.BusinessObject.Amount = value; }
}
public DateTime Dt {
get { return this.BusinessObject.Dt.ToDateTime(); }
set { this.BusinessObject.Dt = LocalDateTime.FromDateTime(value).Date; }
}
public string TimeZone {
get { return this.BusinessObject.TimeZone.Id; }
set { this.BusinessObject.TimeZone = DateTimeZoneProviders.Tzdb.GetZoneOrNull(value); }
}
public string Description {
get { return this.BusinessObject.Description; }
set { this.BusinessObject.Description = value; }
}
}
public string Id { get; private set; }
public decimal Amount { get; private set; }
public LocalDate Dt { get; private set; }
public DateTimeZone TimeZone { get; private set; }
public string Description { get; private set; }
public BusinessObject() { }
public BusinessObject(string id, decimal amount, LocalDate dt, DateTimeZone timeZone, string description) {
this.Id = id;
this.Amount = amount;
this.Dt = dt;
this.TimeZone = timeZone;
this.Description = description;
}
}
我希望很快就可以为应该使用自定义代码处理的特定类型定义钩子/回调,并且OrmLite将允许具有私有setter的属性从持久性中重新加载(目前它只能在一个方向上工作) )。
更新(2014/03/08):作为临时解决方法,可以让OrmLite首先调用自定义序列化/反序列化:
JsConfig<BusinessObject>.TreatValueAsRefType = true;
即使BusinessObject
是参考类型。然后,您可以享受美丽/简单/无处不在:
JsConfig<BusinessObject>.RawSerializeFn = bo => bo.Serialize();
JsConfig<BusinessObject>.RawDeserializeFn = str => BusinessObject.Deserialize(str);
希望很快就会添加对自定义映射的支持(例如,可以将NodaTime.LocalDate映射到DateTime而不是字符串)。
答案 1 :(得分:2)
OrmLite现在支持pluggable text serializers。
可插入序列化允许您为每个可用的RDBMS提供程序指定复杂类型的不同序列化策略,例如:
//ServiceStack's JSON and JSV Format
SqliteDialect.Provider.StringSerializer = new JsvStringSerializer();
PostgreSqlDialect.Provider.StringSerializer = new JsonStringSerializer();
//.NET's XML and JSON DataContract serializers
SqlServerDialect.Provider.StringSerializer = new DataContractSerializer();
MySqlDialect.Provider.StringSerializer = new JsonDataContractSerializer();
//.NET XmlSerializer
OracleDialect.Provider.StringSerializer = new XmlSerializableSerializer();
您还可以通过实施提供自定义序列化策略 IStringSerializer:
public interface IStringSerializer
{
To DeserializeFromString<To>(string serializedText);
object DeserializeFromString(string serializedText, Type type);
string SerializeToString<TFrom>(TFrom from);
}
答案 2 :(得分:2)
要序列化复杂类型,请在JsConfig
上设置您自己的序列化程序(和反序列化程序):
JsConfig<Foo>.SerializeFn = foo => foo.ToString("XOXO", CultureInfo.InvariantCulture);
JsConfig<Foo>.DeSerializeFn = foo =>
{
var result = Foo.Parse(foo, CultureInfo.InvariantCulture);
return result;
};
您可能还想告诉JsConfig假设UTC日期:
JsConfig.Init(new Config {
JsConfig.AssumeUtc = true
});