2017-03-28 2 views
1

ich ServiceStack.Text bin mit Objekten serialisiert/deserialize bevor sie in Redis speichern, aber ich habe über einige Objekte kommen, die wie erwartet nicht deserialisieren.Fehler ServiceStack.Text Verwendung abgeleitet deserialisieren generischer Typ

Ich habe einen Basistyp (Bit von Legacy-Code, mit vielen Projekten mit dieser Art Basis) mit einer Eigenschaft des Typ Objekt. Später wurde eine generische Version des Basistyps hinzugefügt, die die Eigenschaft als generischen Typ darstellt.

Mit ServiceStack.Text zum Serialisieren und Deserialisieren des generischen Typs wird die Eigenschaft für die Basisklasse (type object) festgelegt und nicht der spezifischere Typ für die abgeleitete Klasse.

Eine einfache Konsolenanwendung, die Fehler zu reproduzieren geht ungefähr so:

class Program 
{ 
    public class Base<T> : Base 
    { 
     //hide the Value property on the base class 
     public new T Value { get; set; } 
    } 

    public class Base 
    { 
     public object Value { get; set; } 
    } 

    static void Main(string[] args) 
    { 
     var a = new Base<List<string>>() 
     { 
      Value = new List<string>() { "one", "two", "three" }, 
     }; 

     var serialized = TypeSerializer.SerializeToString(a); 
     var deserialized = TypeSerializer.DeserializeFromString<Base<List<string>>>(serialized); 

     //throws a null ref exception 
     Console.WriteLine(deserialized.Value.Count); 
    } 
} 

einen Haltepunkt nach dem Deserialisierung Einstellung, Visual Studio, das Objekt mit base.Value als Liste <String> mit dem Wert der zeigt, serialisierte Liste, aber die Value-Eigenschaft auf meine Basis < Liste <String> > Klasse ist null.

Screenshot of debugger in Visual Studio

Gibt es eine Möglichkeit TypeSerializer (oder JsonSerializer) richtig einzustellen, um weitere spezifische Eigenschaft anstelle der Eigenschaft auf der Basisklasse zu konfigurieren?

Jede Hilfe wird geschätzt.


aktualisiert

Basierend auf der Antwort, löste ich es, indem die Base<T> und Base erbt von einer neuen abstrakten Basisklasse, etwa so:

public abstract class DummyBase 
{ 
    public string Test { get; set; } = "Test"; 
} 

public class BaseResponse<T> : DummyBase 
{ 
    public T Value { get; set; } 
} 

public class BaseResponse : DummyBase 
{ 
    public object Value { get; set; } 
} 

Antwort

1

Obwohl Base.Value versteckt ist, es zu Reflexion noch sichtbar ist (zB mit a.GetType().GetProperties(). das könnte das Problem sein.

die folg Schuld scheint zu funktionieren. Die Getter und Setter in Base<T> nur Base.Value wickeln. DummyBase<T> ist notwendig ServiceStack deserialisiert die Zeichenfolge auf den richtigen Typ zu erhalten.

class Program 
{ 
    public static void Main (string[] args) 
    { 
     var a = new Base<List<string>>() 
     { 
      Value = new List<string> { "one", "two", "three" }, 
     }; 

     var serialized = TypeSerializer.SerializeToString(a); 
     var deserialized = TypeSerializer.DeserializeFromString<DummyBase<List<string>>>(serialized); 

     // no longer throws a null ref exception 
     Console.WriteLine(deserialized.Value.Count); 
    } 
} 

public class DummyBase<T> 
{ 
    public T Value { get; set; } 
} 

public class Base<T> : Base 
{ 
    public new T Value 
    { 
     get { return (T)base.Value; } 
     set { base.Value = value; } 
    } 
} 

public class Base 
{ 
    public object Value { get; set; } 
} 

Natürlich all dies wäre nicht notwendig, wenn Base<T> nicht von Base erben haben.

+0

Ich habe ein abhängiges Projekt, das den Typ von 'Base ' 'erwartet, so zurück' DummyBase 'ist nicht genau das, was ich will, aber wies mich in die richtige Richtung. Die Basisklasse verfügt über zusätzliche Eigenschaften und Methoden, macht aber die DummyBase zur Basis der generischen und nicht-generischen Klasse. –

Verwandte Themen