2009-05-05 24 views
5

Estoy tratando de construir un objeto que se ve algo como esto:Cómo deserializar Enumerable.ToList <>() a la lista <>

public class MyObject 
    { 
    private IList<AnotherObject> items; 
    public List<AnotherObject> Items 
    { 
     return items.AsEnumerable().ToList<AnotherObject>(); 
    } 
    } 

estoy usando NHibernate como mi DAL y hacer que la cartografía directamente al campo de elementos y todo lo que funciona bien.

También estoy usando Windows Workflow y la actividad del replicador no funciona con el IList genérico. (http://social.msdn.microsoft.com/Forums/en-US/windowsworkflowfoundation/thread/2ca74b60-fd33-4031-be4b-17a79e9afe63) Esto básicamente me obliga a utilizar el contenedor List <> en lugar del IList <>. Esto, por supuesto, rompe el mapeo directo de NHibernate ya que la implementación IList de NHibernate no se puede convertir directamente en una Lista.

** EDITAR: El requisito de Windows Workflow en realidad significa que voy a perder el acceso de tipo seguro a la lista, sin importar lo que requiera un IList.

Ahora el objetivo es serializar/deserializar este objeto. Esto funciona bien con la serialización binaria, pero los objetos subyacentes de NHibernate explotan con los errores de nhibernate cuando intento deserializarlos.

Así que probé la serialización xml. La serialización funciona bien y me da mis buenas definiciones de clase concretas en el archivo xml serializado que elimina por completo los proxies nhibernate. Sin embargo, cuando intento deserializar esto, no puedo agregar los elementos a la lista como la llamada items.AsEnumerable.ToList no permitirá que los elementos se agreguen a la lista subyacente a través del método .Add.

¿Alguien tiene alguna idea al respecto? ¿Voy por esto de la manera incorrecta?

** EDITAR: La clase de hormigón NHibernate es NHibernate.Collection.Generic.PersistentGenericBag que sí implementa IList directamente. Sin embargo, perdí todos los beneficios de tipo seguro de la lista genérica. Esto me devuelve al reino de tener que escribir un contenedor para cada objeto hijo y realmente quería evitar eso si es posible.

Respuesta

2

En opción es crear su propia implementación CustomList que es envoltura alrededor de una instancia que implementa IList

es decir:

public CustomList<AnotherObject> Items  
{  
    return new CustomList<AnotherObject>(items); 
} 

es decir, cuando se agrega a su CustomList<T> se suma a la lista de respaldo.

Parece que mientras su clase implemente IList y IList<T>, estará bien.

+0

Estoy contemplando la ruta envoltorio, pero realmente no quiero tener que escribir un contenedor para cada objeto hijo en mi modelo de dominio. ¿Cuál es el punto de los genéricos entonces? :) Sin embargo, admitiré que esta es probablemente una solución de último recurso. –

+0

La solución actual que estoy trabajando tiene una clase de contenedor que implementa tanto IList y IList . Los métodos no genéricos se han escrito para hacer la verificación de tipos. Pero básicamente solo envuelve un IList interno . –

1

Sí, lamentablemente no puede hacerlo de esta manera. Llamar al ToList() crea una nueva instancia de la lista, por lo que cuando agrega elementos a esa instancia no se reflejarán en la lista original (como claramente ha descubierto).

No uso NHibernate, pero me gustaría saber si su contenedor implementa IList (la versión no genérica). Desde el hilo al que hizo referencia, parece que System.Collections.IList es lo que realmente se requiere (y que está implementado por List<T>, por lo que funciona). ¿Su contenedor implementa IList?

+1

que tienen que utilizar IList con el fin de dar cabida a NHibernate pero Windows Workflow requiere Lista . El –

+0

NHibernate.Collection.Generic.PersistentGenericBag en efecto, poner en práctica IList. Podría usar esto pero luego perderé la seguridad tipo de la lista genérica que no quería. La alternativa es escribir un contenedor como lo sugiere Alex a continuación, pero no es mi solución ideal. –

+1

No importa lo que haga, perderá seguridad de tipo. Esta es la razón por la cual la Lista no implementa IList; requiere que abra una interfaz que le permitirá, sintácticamente, agregar un elemento que no coincida con el tipo del genérico. ¿Vas a acceder a este IList en el "otro lado" de la serialización? ¿No podrán emitir de nuevo a un IList si ese es el caso? –

0

¿No puedes simplemente echarlo así?

public class MyObject 
{ 
    private IList<AnotherObject> items; 
    public List<AnotherObject> Items() 
    { 
     return (List<AnotherObject>)items; 
    } 
} 

Havent tenía el chanse para probarlo, pero creo que debería funcionar.

+1

esto no funciona debido a que el objeto subyacente en el IList es una NHibernate.Collection.Generic.PersistentGenericBag que no es directamente moldeable a una lista

+0

Ah, ok, entonces no importa mi respuesta: S – fredrik

0

creo que la colección (no genérico) NHibernate PersistentBag implementa IList por lo que podría escribir artículos como IList en lugar de IList<AnotherObject>. El enlace en su pregunta afirma que el problema es que replicador requiere un IList cuales List<T> implementos pero no IList<T> (que figura).

+0

comentario Véase más arriba de Adán en cuanto a por qué IList no implementa IList. No lo había pensado antes. –

0

¿Puede ser echados a IEnumerable <T>? Usted podría intentar esto:

public class MyObject 
{ 
    private IList<AnotherObject> items; 
    public List<AnotherObject> Items 
    { 
     return new List<AnotherObject>items.Cast<AnotherObject>()); 
    } 
    // or, to prevent modifying the list 
    public IEnumerable<AnotherObject> Items 
    { 
     return items.Cast<AnotherObject>(); 
    } 
} 
+0

Necesito un IList para Windows Workflow. –

Cuestiones relacionadas