2016-03-27 11 views
1

Ich habe eine Klasse mit der folgenden Strukturzuordnen/Deserialize generisches Objekt mit mehr abgeleiteten Typ in die einem mit weniger abgeleiteten Typ

public class GenericEntity<T> 
    where T : BaseClass 
{ 
    T Property {get; set;} 
} 

Ich habe mehr konkreten Implementierungen von BaseClass und bin diese konkreten Implementierungen unter Verwendung von Objekt zu instanziiert vom Typ GenericEntity

z var entity = new GenericEntity<DerivedClass>()

Ich dränge diese Entität in ein Messaging-Framework durch Serialisierung des Objekts in JSON (mit Newtonsoft). Am anderen Ende extrahiere ich diese Nachricht (JSON) aus der Nachrichtenwarteschlange und versuche, die Nachricht in den Typ GenericEntity<BaseClass> mit JsonSerializerSettings TypeNameHandling.All zu deserialisieren. Aber zum Zeitpunkt der Deserialisierung, wirft es JsonSerializationException mit Details

Typ angegeben in JSON ‚NewtonsoftPlayground.GenericEntity 1[[NewtonsoftPlayground.DerivedClass, NewtonsoftPlayground, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], NewtonsoftPlayground, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not compatible with 'NewtonsoftPlayground.GenericEntity 1 [[NewtonsoftPlayground.BaseClass, NewtonsoftPlayground, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null] ], NewtonsoftPlayground, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null '.

Wie kann ich das erreichen? Oder sollte ich nicht generisch verwenden? Wenn das der Fall ist, würde ich überall nach dem Extrahieren von Nachrichten aus der Warteschlange Typumwandlungen schreiben, was ich zu vermeiden versuche.

Antwort

0

Ich konnte keine direkte Lösung finden, um dies zu erreichen. Wie von @Tamas Ionut vorgeschlagen, werden durch das Angeben der Basisklasse beim Deserialisieren die Eigenschaften der konkreten Klasse nicht deserialisiert.

Als Workaround habe ich eine statische Methode erstellt, die im Prinzip GenericEntity<BaseClass> instanziiert und alle Eigenschaften in Reflektion kopiert.

public static GenericEntity<BaseClass> ConvertToBaseEntity(object model) 
    { 
     if (model.GetType().GetGenericTypeDefinition() != typeof(GenericEntity<>)) 
     { 
      throw new ArgumentException(
       "Model should be of type GenericEntity<T>.", "model"); 
     } 

     GenericEntity<BaseClass> baseModel = new GenericEntity<BaseClass>(); 

     foreach (var propertyInfo in model.GetType().GetProperties()) 
     { 
      baseModel.GetType().GetProperty(propertyInfo.Name).SetValue(baseModel, propertyInfo.GetValue(model)); 
     } 

     return baseModel; 
    } 

Ich hoffe, das hilft jemandem.

1

Ich habe den folgenden Code neu:

public class GenericEntity<T> where T : BaseClass 
    { 
    public T Property { get; set; } 
} 

public class BaseClass { 
} 

class Derived1 : BaseClass 
{ 
    public int Age { get; set; } 
} 

class Derived2 : BaseClass { 
    public string Name { get; set; } 
} 

.... 

static void Main() 
    { 
     Derived1 d1 = new Derived1 {Age = 23}; 
     GenericEntity<Derived1> entity = new GenericEntity<Derived1> {Property = d1}; 

     var data = JsonConvert.SerializeObject(entity, new JsonSerializerSettings() { 
      TypeNameHandling = TypeNameHandling.All 
     }); 
     var baseEntity = JsonConvert.DeserializeObject(data, typeof(GenericEntity<BaseClass>)); 
} 

ich keine Fehlermeldungen erhalten, während die Daten deserialisiert. Lassen Sie mich wissen, in welchem ​​Zusammenhang und wie es sich unterscheidet.

Dies wird sich natürlich nicht:

 BaseClass d1 = new Derived1 {Age = 23}; 
     GenericEntity<BaseClass> entity = new GenericEntity<BaseClass> {Property = d1}; 

     var data = JsonConvert.SerializeObject(entity, new JsonSerializerSettings() { 
      TypeNameHandling = TypeNameHandling.All 
     }); 
     var baseEntity = JsonConvert.DeserializeObject<GenericEntity<Derived1>>(data, new JsonSerializerSettings() 
     { 
      TypeNameHandling = TypeNameHandling.All 
     }); 

Wenn Sie eine Baseclass serialisiert, es ist nicht verantwortlich sein werden alle zusätzlichen Details von Serialisierung, dass die Fachklasse (ich meine, Sie wollten eine Baseclass serialisiert und genau das wirst du serialisieren).

Es ist Ihre Aufgabe, sie als spezialisierte Instanzen zu serialisieren: Das heißt, wenn Sie eine BaseClass erhalten und Sie wissen, dass Sie eine Derived1 als Instanz1 analysieren und dann serialisieren müssen.

+0

Hallo @Tamas Ionut, wenn Sie 'TypeNameHandling.All' Einstellungen während der Serialisierung verwenden, erhalten Sie den Fehler. In dem Code, den Sie ausprobiert haben, wird das Objekt zur Basisklasse deserialisiert, aber abgeleitete Klasseneigenschaftswerte werden nicht berücksichtigt. Was ich versuche zu erreichen, ist, dass deserialisierte Instanz vom Typ 'Derived1' sein sollte, aber die Schnittstelle sollte vom Typ' BaseClass' sein. Ich hoffe, dass dies weiter geht. Vielen Dank. –

+0

Ich stimme dir zu. Ich bin nur spezialisiert Klasse.Ich bin Serialisierung Instanz des Typs 'GenericEntity ', aber zum Zeitpunkt der Deserialisierung möchte ich es 'GenericEntity ' halten Instanz des Typs 'GenericEntity '. –

+0

Ich versuche dies zu erreichen: 'Derived1 d1 = new Derived1 {Age = 23}; GenericEntity entity = new GenericEntity {Eigenschaft = d1}; var data = JsonConvert.SerializeObject (Entität, neue JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All }); var baseEntity = JsonConvert.DeserializeObject > (Daten, neue JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All }); ' –