Ottenere proxy del tipo corretto in NHibernate

Ottenere proxy del tipo corretto in NHibernate

È più facile disattivare il caricamento lento per la classe degli animali. Dici che è per lo più nella memoria comunque.

<class name="Animal" lazy="false">
<!-- ... -->
</class>

In alternativa, puoi anche utilizzare no-proxy , guarda questo post:

<property name="OwnedAnimal" lazy="no-proxy"/>

Per quanto posso vedere, funziona solo quando il AnimalOwner in realtà è un proxy.

O

Puoi usare i generici sul proprietario dell'animale per rendere il riferimento una classe concreta.

class AnimalOwner<TAnimal>
{
  virtual TAnimal OwnedAnimal {get;set;}
}

class CatOwner : AnimalOwner<Cat>
{
}

class DogOwner : AnimalOwner<Dog>
{
}

O

Puoi mappare il DogOwners e CatOwners in tabelle separate e definire il tipo di animale concreto nella mappatura.

<class name="CatOwner">
  <!-- ... -->
  <property name="OwnedAninal" class="Cat"/>
</class>
<class name="DogOwner">
  <!-- ... -->
  <property name="OwnedAninal" class="Dog"/>
</class>

O

Scambi un po' con NHibernate, come proposto in questo blog. NH è effettivamente in grado di restituire l'oggetto reale dietro il proxy. Qui un'implementazione un po' più semplice come quella proposta lì:

    public static T CastEntity<T>(this object entity) where T: class
    {
        var proxy = entity as INHibernateProxy;
        if (proxy != null)
        {
            return proxy.HibernateLazyInitializer.GetImplementation() as T;
        }
        else
        {
            return entity as T;
        }
    }

che può essere utilizzato in questo modo:

Dog dog = dogOwner.OwnedAnimal.CastEntity<Dog>();

Penso che di recente abbiamo avuto un problema simile, la soluzione AFAIR è stata quella di dare ad "Animal" un "metodo/proprietà" autonomo:

public Animal Self { get { return this; } }

Questo potrebbe quindi essere lanciato per correggere "animale". Quello che succede è che il tuo oggetto originale ha un riferimento all'oggetto proxy nhibernate (quando è caricato pigramente), che funge da Animal per tutti i metodi esposti tramite la classe Animal (passa tutte le chiamate all'oggetto caricato). Tuttavia non può essere lanciato come nessuno dei tuoi altri animali perché non è nessuno di questi, emula solo la classe Animal. Tuttavia la classe che è incapsulata da AnimalProxy può essere lanciata come sottoclasse animal perché è un'istanza reale della classe corretta, devi solo arrivare al suo this riferimento.