7

Ich verwende ServiceStack.Ormlite, um Daten in einer SQLite Datenbank persistent zu speichern, und ziemlich glücklich damit bisher.Wie kann ich die Serialisierung/Deserialisierung eines komplexen Typs in ServiceStack.OrmLite anpassen

Viele meiner Objekte haben jedoch Eigenschaften eines komplexen Typs, die ich nicht mit JSV serialisiert werden möchte.

Ich muss in der Lage sein, eine benutzerdefinierte Serialisierung/Deserialisierung anzugeben, die zum Speichern der Eigenschaft in der Datenbank (als Zeichenfolge) verwendet werden soll. In der Welt db4o würde dies der Verwendung der von IObjectConstructor bereitgestellten Übersetzungsfunktion entsprechen.

Ein gutes Beispiel für komplexe Typen, die nicht serialisiert und deserialisiert werden können, sind NodaTime-Typen, obwohl sie sich leicht in Strings umwandeln lassen (ich habe bereits die Serialisierungs-/Deserialisierungsfunktionen, die ich mit db4o verwendet habe).

Was ist der einfachste Weg, um das zu erreichen? Ein Wrapper wäre nicht sehr praktisch, da ich für jeden Typ, der eine Eigenschaft dieses komplexen Typs enthält, einen schreiben und pflegen müsste.

+0

Bitte geben Sie eine ein minimales Arbeitsbeispiel einer Klasse, wie möchten Sie es realisieren und wie Sie es deserelisieren. – htellez

+0

Es ist sehr einfach, ich habe eine Basisklasse mit einer komplexen Eigenschaft. Ich brauche diese Eigenschaft serialisiert/deserialisiert in/aus einer Zeichenfolge mit meiner eigenen Routine statt JSV. Ich glaube nicht, dass ein Code-Sample in diesem speziellen Fall wirklich benötigt wird. –

Antwort

6

Für diejenigen, die sich für das Wrapper-Muster interessieren, das ich derzeit verwende, um benutzerdefinierte Serialisierung mit Ormlite zu implementieren (funktioniert auch mit anderen ORMs), hier ist ein einfaches Arbeitsbeispiel mit NodaTime Typen, die sonst nicht serialisiert werden richtig:

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; 
    } 
} 

Ich hoffe, dass es bald möglich sein wird, Haken/Rückrufe für bestimmte Typen zu definieren, die mit benutzerdefinierten Code behandelt werden soll, und auch, dass OrmLite werden Eigenschaften mit privaten Setter erlauben aus Persistenz neu geladen werden (zur Zeit funktioniert es nur in einer Richtung).

Update (2014.03.08): als eine vorübergehende Lösung ist es möglich, OrmLite Verwendung benutzerdefinierte Serialisierung/Deserialisierung zu haben, zuerst durch den Aufruf:

JsConfig<BusinessObject>.TreatValueAsRefType = true; 

Auch wenn BusinessObject ist ein Referenztyp. Dann können Sie die Schönheit/Einfachheit/Allgegenwart genießen:

JsConfig<BusinessObject>.RawSerializeFn = bo => bo.Serialize(); 
JsConfig<BusinessObject>.RawDeserializeFn = str => BusinessObject.Deserialize(str); 

Hoffentlich Unterstützung für benutzerdefiniertes Mapping in Kürze hinzugefügt werden (so dass zum Beispiel kann ein NodaTime.LocalDate zu einem DateTime- anstelle einer Zeichenfolge zugeordnet werden).

+0

Ich sehe wirklich nicht, wie private Setter extern geladen werden könnten, oder ob sie es überhaupt tun sollten. 'protected' könnte jedoch funktionieren. – ANeves

+1

Private Setter sind mit Reflection zugänglich. –

2

OrmLite unterstützt jetzt pluggable text serializers.

Steckbare Serialisierung können Sie verschiedene Serialisierung Strategien der Komplexe Typen für jeden verfügbaren RDBMS-Anbieter angeben, zum Beispiel:

//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(); 

Sie können auch eine benutzerdefinierte Serialisierung Strategie bieten durch Umsetzung IStringSerializer:

public interface IStringSerializer 
{ 
    To DeserializeFromString<To>(string serializedText); 
    object DeserializeFromString(string serializedText, Type type); 
    string SerializeToString<TFrom>(TFrom from); 
} 
2

Um komplexe Typen, richten Sie Ihren eigenen Serializer (und Deserializer) auf JsConfig serialisiert:

JsConfig<Foo>.SerializeFn = foo => foo.ToString("XOXO", CultureInfo.InvariantCulture); 
JsConfig<Foo>.DeSerializeFn = foo => 
{ 
    var result = Foo.Parse(foo, CultureInfo.InvariantCulture); 
    return result; 
}; 

Sie auch Daten UTC übernehmen wollen könnte JsConfig sagen:

JsConfig.AssumeUtc = true; 
+0

Funktioniert das mit OrmLite? Ich weiß, dass es mit ServiceStack funktioniert, aber soweit ich es mit meinem Code gelesen und getestet habe, wurde es für die OrmLite-Serialisierung nicht berücksichtigt. –

+0

Es tut. Aber ich habe [Probleme mit der Serialisierung von Strukturen] (http://stackoverflow.com/questions/20246508/make-ormlite-use-proper-serialization-for-structs). (Deserialisierung funktioniert gut. Und für Referenztypen funktionieren beide gut - Serialisierung und Deserialisierung.) – ANeves

Verwandte Themen