簡體   English   中英

如何在ServiceStack.OrmLite中自定義復雜類型的序列化/反序列化

[英]How can I customize the serialization/deserialization of a complex type in ServiceStack.OrmLite

我使用ServiceStack.OrmLite將數據保存在SQLite數據庫中,到目前為止對它非常滿意。

但是,我的許多對象都具有復雜類型的屬性,我不希望使用JSV序列化。

我需要能夠指定應該用於在數據庫中存儲屬性的自定義序列化/反序列化(作為字符串)。 db4o世界中,這相當於使用IObjectConstructor提供的轉換功能。

無法正確序列化和反序列化的復雜類型的一個很好的例子是NodaTime類型,即使它們可以很容易地映射到字符串(我已經有了與db4o使用的序列化/反序列化函數)。

實現這一目標的最簡單方法是什么? 包裝器不是很方便,因為我必須為包含這種復雜類型屬性的每種類型編寫和維護一個包裝器。

對於那些可能對包裝模式感興趣的人,我目前正在使用OrmLite實現自定義序列化(也可以與其他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而不是字符串)。

OrmLite現在支持可插入文本序列化程序

可插入序列化允許您為每個可用的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);
}

要序列化復雜類型,請在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
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM