Daniel Kolman

NHibernate, lazy proxy třídy a chyba C# kompilátoru

| 0 comments |

Kompilátor C# v .NET verze 2.0 obsahuje chybu, díky které při použití where T : class pro omezení typového parametru generické třídy vygeneruje špatný IL kód. Díky tomu se takovou assembly vůbec nepodaří nahrát do paměti, runtime vyhodí výjimku:

System.BadImageFormatException: An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)

Popis naleznete na Microsoftu nebo taky na Ayendeho blogu.

Když používáte NHibernate, a zvlášť pokud jste právě přešli na verzi 1.2, může se tato výjimka objevit i když vůbec where T : class nepoužijete. Jak to? NHibernate vám při načtení objektu může místo vaší třídy vrátit dynamicky generovanou proxy třídu (a ve verzi 1.2 je to default). V ní jsou všechny virtual members nahrazeny proxy metodou, která při prvním přístupu k objektu tento objekt načte z databáze (materializuje). No a když ve vašem objektu použijete virtuální metodu s generickým parametrem, např:

protected virtual T GetProperty<T>(string name)
{
...
}

snadno se dopracujete k výše zmíněné výjimce. Je to pravděpodobně (hlouběji jsem to nezkoumal) způsobeno tím, že generátor dynamické proxy třídy (Castle.DynamicProxy.dll) se pokouší emitovat kód, který podmínku where T : class obsahuje, a pokus nahrát tuto třídu do paměti skončí s chybou. Proto používáte-li NHibernate a "lazy" načítání objektů, nepoužívejte virtuální generické metody.