2012-03-28 11 views
10

Pude hacer una corrección con JSON.net TypeNameHandling. Estoy almacenando un objeto con formato JSON usando RavenDB y establezco TypeNameHandling del serializador JSON.net en true para poder manejar una estructura de herencia que tengo en su lugar.Manejando los cambios del espacio de nombres con TypeNameHandling.All

Necesitaba cambiar el espacio de nombre del documento que estoy almacenando, por lo que ahora cuando se deserializa arroja el error "Error al resolver el tipo especificado en JSON" porque la referencia al tipo en el documento JSON ya no existe .

¿Es posible interceptar la deserialización de Json para realizar algún tipo de migración progresiva?

Gracias,

Respuesta

18

Ok, lo resolvió. Al final fue bastante sencillo. Debe sobrescribir el DefaultSerializationBinder que es responsable de crear el tipo .Net del documento. Como mi documento json tiene el antiguo espacio de nombres, tuve que interceptar la creación de ese tipo para devolver el tipo correcto. Junté una implementación simple que te permitirá configurar "migraciones" cuando se crea el serializador 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); 
     } 
    } 

Cuando la interfaz es

public interface INamespaceMigration 
{ 
    string FromAssembly { get; } 

    string FromType { get; } 

    Type ToType { get; } 
} 
+3

para aquellos que se preguntan cómo conectarlo, es así: documentStore.Conventions.CustomizeJsonSerializer = serializer => serializer.Binder = new NamespaceMigrationSerializationBinder (migrations); – NeilD

+0

Esta es una gran solución para la migración del espacio de nombres en RavenDB. ¡¡¡Muchas gracias!!! – marisks

+0

Creo que es posible que desee sobrescribir BindToName también, o sus rescates pueden tener un $ type = "". Podría hacer algo como: override público void BindToName (Tipo serializedType, out string assemblyName, out string typeName) { typeName = serializedType.FullName; assemblyName = serializedType.Assembly.FullName; – pomarc

0

puede utilizar un DocumentConversionListener para hacer esto. Por favor, eche un vistazo aquí: http://ayende.com/blog/66563/ravendb-migrations-rolling-updates

+0

Gracias Daniel. Pero el problema ocurre antes de que pueda llegar aquí. Si observa la interfaz de IDocumentConversionListener, verá que está enviando el objeto deserializado. Mi problema es que está fallando en la deserialización. –

+0

Tiene un parámetro 'documento' de tipo RavenJObject, que es el árbol json antes de que se deserialice. Esto debería permitirle cambiar el valor de la propiedad antes de que se deserialice en el objeto/propiedad. Espero que ayude; si no, publique un código. –

Cuestiones relacionadas