2012-03-28 12 views
10

Udało mi się samemu naprawić poprawkę za pomocą JSON.net TypeNameHandling. Przechowuję obiekt sformatowany w JSON przy użyciu RavenDB i ustawię TypeNameHandling serializatora JSON.net na wartość true, aby poradzić sobie ze strukturą dziedziczenia, którą posiadam.Obsługa zmian przestrzeni nazw za pomocą TypeNameHandling.All

Potrzebowałem zmienić przestrzeń nazw przechowywanego dokumentu, więc teraz, gdy jest deserialzed, generuje błąd "Błąd rozwiązujący typ określony w JSON", ponieważ odwołanie do typu w dokumencie JSON już nie istnieje .

Czy możliwe jest przechwycenie deserializacji Json w celu przeprowadzenia migracji?

Dzięki,

Odpowiedz

18

OK, wymyśliłem to. W końcu było całkiem prosto. Musisz zastąpić DefaultSerializationBinder, który jest odpowiedzialny za utworzenie typu .Net z dokumentu. Ponieważ mój dokument json ma starą przestrzeń nazw, musiałem przechwycić tworzenie tego typu, aby zwrócić właściwy typ. Przygotowałem prostą implementację, która pozwoli ci skonfigurować "migracje" podczas tworzenia serializatora JSON.

public class NamespaceMigrationSerializationBinder : DefaultSerializationBinder 
    { 
     private readonly INamespaceMigration[] _migrations; 

     public NamespaceMigrationSerializationBinder(params INamespaceMigration[] migrations) 
     { 
      _migrations = migrations; 
     } 

     public override Type BindToType(string assemblyName, string typeName) 
     { 
      var migration = _migrations.SingleOrDefault(p => p.FromAssembly == assemblyName && p.FromType == typeName); 
      if(migration != null) 
      { 
       return migration.ToType; 
      } 
      return base.BindToType(assemblyName, typeName); 
     } 
    } 

Jeżeli interfejs jest

public interface INamespaceMigration 
{ 
    string FromAssembly { get; } 

    string FromType { get; } 

    Type ToType { get; } 
} 
+3

dla tych, którzy zastanawiają się, jak je podłączyć, to tak: documentStore.Conventions.CustomizeJsonSerializer = serializer => serializer.Binder = new NamespaceMigrationSerializationBinder (migracje); – NeilD

+0

To świetne rozwiązanie do migracji nazw w RavenDB. Wielkie dzięki!!! – marisks

+0

Myślę, że możesz również przesłonić nazwę BindToName, lub twoje zapisy mogą mieć $ type = "". Możesz zrobić coś takiego: publiczne zastąpienie void BindToName (Type serializedType, out ciąg assemblyName, out ciąg typeName) { typeName = serializedType.FullName; assemblyName = serializedType.Assembly.FullName; – pomarc

0

można użyć DocumentConversionListener to zrobić. Proszę spojrzeć tutaj: http://ayende.com/blog/66563/ravendb-migrations-rolling-updates

+0

Dzięki Daniel. Ale problem występuje, zanim będzie mógł się tu dostać. Jeśli spojrzysz na interfejs obiektu IDocumentConversionListener, zobaczysz, że wysyła on obiekt z deserializacją. Mój problem polega na tym, że nie działa w przypadku deserializacji. –

+0

Masz parametr "dokument" typu RavenJObject, który jest drzewem json przed deserializacją. Powinno to umożliwić zmianę wartości właściwości przed przekształceniem jej w obiekt/właściwość. Nadzieję, że pomaga - jeśli nie, proszę napisać kod. –