Hola a todos! Les presento mi problema que debe ser muy parecido a otros problemas de serializacion como el en caso de serializar JSON. En mi caso, tengo el problema de que tengo que realizar una exportación de una lista de entidades a XML y cuando quiero realizarla tuve que hacer un par de *walkarounds* para poder realizar algo cercano sin tener que caer en los DTOs ya que, a futuro, voy a estar duplicando todo el dominio para poder serializar.
*Historia:* De primera, intente serializar a XML de una pero me tope con que no se puede serializar interfaces. Entonces, investigando un poco caí en este tema de StackOverflow donde aparece el primer walkaround: Xml Deserialization with Proxy <http://stackoverflow.com/questions/14225568/xml-deserialization-with-proxy> Implemente el walkaround pero me siguió molestando con una ProxyAccesException donde me dice, en resumen, que no puede convertir un PersistentBag a List<T>. Eso me lo tira en el repositorio genérico para NH que tengo incluido aca.. Mirando el mapping no encontré en ningún lado que haya mapeado un List<T>, ademas, NH no te lo permite realizar. Entonces, mirando en profundidad, únicas propiedades que retornan un List<T> son las la que surrogan las listas cuando se serializa a XML. El tema acá es que no están mapeadas esas listas, por ende, el mapping debería ignorar estas propiedades. Y lo peor de todo, es que la excepción que me tira es a causa de esto. Entonces, busque una manera de que ignore a mano las propiedades pero nada (Ignoring methods on entity types with nHibernate <http://stackoverflow.com/questions/1120574/ignoring-methods-on-entity-types-with-nhibernate> ). Sigo leyendo otras cosas por las cuales puede resolver y "deshabilite" el lazyload de la entidad y los de los bags. También encontré una magia para desproxificar las entidades (Hacking lazy loaded inheritance <http://sessionfactory.blogspot.com.ar/2010/08/hacking-lazy-loaded-inheritance.html> y WCF + NHibernate: Entity Serialization <http://nhibernate.info/doc/howto/various/wcf-nhibernate-entity-serialization.html>) pero nada... Acá les dejo el código necesario para que puedan ver donde puede haber una solución para esto. Si necesitan revisar mas en profundidad, les dejo el repositorio de github: escuela-simple <https://github.com/drielnox/escuela-simple> *Entidad:* namespace EscuelaSimple.Modelos { [Serializable()] public class Personal : IEntidad<uint> { [XmlAttribute] public virtual uint Identificador { get; set; } public virtual string Nombre { get; set; } public virtual string Apellido { get; set; } public virtual uint DNI { get; set; } public virtual DateTime FechaNacimiento { get; set; } public virtual string Domicilio { get; set; } public virtual string Localidad { get; set; } [XmlIgnore] public virtual ICollection<Telefono> Telefonos { get; protected set; } [XmlElementAttribute(IsNullable = true)] public virtual DateTime? IngresoDocencia { get; set; } [XmlElementAttribute(IsNullable = true)] public virtual DateTime? IngresoEstablecimiento { get; set; } public virtual string Titulo { get; set; } public virtual string Cargo { get; set; } public virtual string SituacionRevista { get; set; } public virtual string Observacion { get; set; } [XmlIgnore] public virtual ICollection<Inasistencia> Inasistencias { get; protected set; } public Personal() { this.Telefonos = new List<Telefono>(); this.Inasistencias = new List<Inasistencia>(); } public void AgregarTelefono(Telefono telefono) { if (!this.Telefonos.Contains(telefono)) { this.Telefonos.Add(telefono); } } public void QuitarTelefono(Telefono telefono) { if (this.Telefonos.Contains(telefono)) { this.Telefonos.Remove(telefono); } } public void AgregarInasistencia(Inasistencia inasistencia) { if (!this.Inasistencias.Contains(inasistencia)) { this.Inasistencias.Add(inasistencia); } } public void QuitarInasistencia(Inasistencia inasistencia) { if (this.Inasistencias.Contains(inasistencia)) { this.Inasistencias.Remove(inasistencia); } } #region Surrogacion para XMLSerializer [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] [XmlArray(ElementName = "Telefonos"), XmlArrayItem("Telefono", typeof(Telefono))] public virtual List<Telefono> ListaDeTelefonosSurrogado { get { List<Telefono> proxy = this.Telefonos as List<Telefono>; if (proxy == null && this.Telefonos != null) { proxy = (List<Telefono>)this.Telefonos; } return proxy; } set { this.Telefonos = value; } } [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] [XmlArray(ElementName = "Inasistencias"), XmlArrayItem("Inasistencia", typeof(Inasistencia))] public virtual List<Inasistencia> ListaDeInasistenciasSurrogada { get { List<Inasistencia> proxy = this.Inasistencias as List<Inasistencia>; if (proxy == null && this.Inasistencias != null) { proxy = (List<Inasistencia>)this.Inasistencias; } return proxy; } set { this.Inasistencias = value; } } #endregion #region Sobrecarga a Object public override bool Equals(object obj) { if (obj == null) { return false; } Personal personal = obj as Personal; if (personal == null) { return false; } return this.Identificador.Equals(personal.Identificador) && this.Nombre.Equals(personal.Nombre) && this.Apellido.Equals(personal.Apellido) && this.DNI.Equals(personal.DNI) && this.FechaNacimiento.Equals(personal.FechaNacimiento); } public override int GetHashCode() { string hashCode = this.Identificador + "|" + this.Nombre + "|" + this.Apellido + "|" + this.DNI + "|" + this.FechaNacimiento + "|" + this.Domicilio + "|" + this.Localidad + "|" + this.Telefonos + "|" + this.IngresoDocencia + "|" + this.IngresoEstablecimiento + "|" + this.Titulo + "|" + this.Cargo + "|" + this.SituacionRevista + "|" + this.Observacion + "|" + this.Inasistencias; return hashCode.GetHashCode(); } #endregion } } Mapping: namespace EscuelaSimple.Datos.Mapeo.NHibernate { public class PersonalMap : ClassMapping<Personal> { public PersonalMap() { Lazy(false); Table("Personal"); Id<uint>(x => x.Identificador, m => { m.Access(Accessor.Property); m.Column("IdPersonal"); m.Generator(Generators.Identity); }); Property<string>(x => x.Nombre, m => { m.Access(Accessor.Property); m.Column("Nombre"); m.NotNullable(true); }); Property<string>(x => x.Apellido, m => { m.Access(Accessor.Property); m.Column("Apellido"); m.NotNullable(true); }); Property<uint>(x => x.DNI, m => { m.Access(Accessor.Property); m.Column("DNI"); m.UniqueKey("UK_Personal_DNI"); m.NotNullable(true); }); Property<DateTime>(x => x.FechaNacimiento, m => { m.Access(Accessor.Property); m.Column("FechaNacimiento"); m.NotNullable(true); m.Type<DateType>(); }); Property<string>(x => x.Domicilio, m => { m.Access(Accessor.Property); m.Column("Domicilio"); m.NotNullable(false); }); Property<string>(x => x.Localidad, m => { m.Access(Accessor.Property); m.Column("Localidad"); m.NotNullable(false); }); Property<DateTime?>(x => x.IngresoDocencia, m => { m.Access(Accessor.Property); m.Column("IngresoDocencia"); m.NotNullable(false); m.Type<DateType>(); }); Property<DateTime?>(x => x.IngresoEstablecimiento, m => { m.Access(Accessor.Property); m.Column("IngresoEstablecimiento"); m.NotNullable(false); m.Type<DateType>(); }); Property<string>(x => x.Titulo, m => { m.Access(Accessor.Property); m.Column("Titulo"); m.NotNullable(false); }); Property<string>(x => x.Cargo, m => { m.Access(Accessor.Property); m.Column("Cargo"); m.NotNullable(false); }); Property<string>(x => x.SituacionRevista, m => { m.Access(Accessor.Property); m.Column("SituacionRevista"); m.NotNullable(false); }); Property<string>(x => x.Observacion, m => { m.Access(Accessor.Property); m.Column("Observacion"); m.NotNullable(false); }); Set<Telefono>(x => x.Telefonos, cm => { cm.Access(Accessor.Property); cm.Table("Telefono"); cm.Key(k => { k.Column(c => { c.Name("IdPersonal"); c.NotNullable(true); c.UniqueKey("UK_Telefono_2"); }); k.ForeignKey("FK_Telefono_Personal_1"); k.NotNullable(true); }); cm.Cascade(Cascade.All); cm.Lazy(CollectionLazy.NoLazy); }, m => { m.OneToMany(x => { x.Class(typeof(Telefono)); x.NotFound(NotFoundMode.Exception); }); }); Set<Inasistencia>(x => x.Inasistencias, cm => { cm.Access(Accessor.Property); cm.Table("Inasistencia"); cm.Key(k => { k.Column(c => { c.Name("IdPersonal"); c.NotNullable(true); }); k.ForeignKey("FK_Inasistencia_Personal_1"); k.NotNullable(true); }); cm.Cascade(Cascade.All); cm.Lazy(CollectionLazy.NoLazy); }, m => { m.OneToMany(x => { x.Class(typeof(Inasistencia)); x.NotFound(NotFoundMode.Exception); }); }); } } } *Repositorio generico para NH:* namespace EscuelaSimple.Datos.Repositorio { public abstract class NHibernateRepositorio<TEntidad, TClavePrimaria> : IRepositorio<TEntidad, TClavePrimaria> where TEntidad : class, IEntidad<TClavePrimaria> where TClavePrimaria : struct { public ISession Sesion { get; set; } public NHibernateRepositorio(ISession sesion) { this.Sesion = sesion; } public TEntidad ObtenerPorIdentificador(TClavePrimaria id) { return this.Sesion.Get<TEntidad>(id); } public IEnumerable<TEntidad> ObtenerTodo() { IQueryOver<TEntidad> result = this.Sesion.QueryOver<TEntidad>(); return result.List(); // <<< Aca tira ProxyAccessException!!! } public void Crear(TEntidad entity) { this.Sesion.Save(entity); } public void Actualizar(TEntidad entity) { this.Sesion.Update(entity); } public void Borrar(TEntidad entity) { this.Sesion.Delete(entity); } public TEntidad ObtenerPor(Predicate<TEntidad> predicate) { List<TEntidad> result = this.FiltrarPor(predicate) as List<TEntidad>; return result.Count > 0 ? result[0] : null; } public IEnumerable<TEntidad> FiltrarPor(Predicate<TEntidad> predicate) { List<TEntidad> result = this.ObtenerTodo() as List<TEntidad>; return result.FindAll(predicate); } } } -- -- Para escribir al Grupo, hágalo a esta dirección: NHibernate-Hispano@googlegroups.com Para más, visite: http://groups.google.com/group/NHibernate-Hispano --- Has recibido este mensaje porque estás suscrito al grupo "NHibernate-Hispano" de Grupos de Google. Para anular la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a nhibernate-hispano+unsubscr...@googlegroups.com. Para obtener más opciones, visita https://groups.google.com/d/optout.