Mikor a .NET Framework 4.0 még csak pre-béta állapotban volt, és a leendő újdonságokról csak a legjobban értesült piaci kofáktól lehetett némi információhoz jutni, közismert volt a tény: a caching háza táján muszáj lesz rendet vágni. Egyrészt, nagy szükség lenne egy eloszott cache-re - ez AppFabric Cache (született: Velolcity) néven cirka másfél éve a "még 1-2 hónap, és itt a relese!" állapotban van (de legalább van, és elég ígéretes).
In-process, objektum alapú cache pedig mindig is volt a .NET Frameworkben - viszont volt volt vele egy apró gond: eredetileg webalkalmazások gyorsítására szánták a keretrendszer tervezői, így - bár technikailag egyáltalán semmi akadálya nem volt, hogy ASP.NET alkalmazásokon kívül is használhassuk - mégis, ez a megoldás, mondjuk ki nyílt proletár őszinteséggel: meglehetősen bénácska volt.
A leggyakoribb ellenvetések azok voltak, hogy egyrészt, milyen már, hogy a System.Web assemblyt be kell referenciálni egy olyan alkalmazásba, aminek nem sok köze van a webhez, másrészt, ez a cache implementáció nagyon sok "beégetett" dolgot tartalmazott, konkrétan nem igazán lehetett bővíteni, testre szabni sehogyan sem.
Erre már a 4.0 első bétáiban körvonalazódott a megoldás: egy vadi új object cache implementáció, ami meglehetősen jól kusztomizálható, sőt, mi több: a System.Web.Cachig-et is átdolgozzák, pontosabban az implementációt kihajítják, a régi API pedig csak egy proxy, egy kompatibilitási réteg lesz az új cache fölött a legacy alkalmazások számára, hogy a kompatibilitás megmaradjon.
Most alaposan megreflektoroztam mind a régi, mind az új cache-t, és hát mivel nem vagyok a szavak embere, inkább idézném a Hooligans zenekar örökbecsű számát, ami a System.Web szerelvény 4.0-ás verziójában található cache implementációról írtak:
Hiába kéred, nem változom meg
Ilyen vagyok, más nem leszek
Ne szólj rám, ne változtass meg
Nem akarom, hogy irányíts, nem engedem
Nem akarom, hogy azt hidd, jobb lettem
Mert egy nap neked mindent megtettem
Bennem minden a régi, te rólam mást hittél
Mert a vér nem válik, a vér nem válik vízzé
Na szóval ez kurvára ugyanaz, mint a régi. Emelett persze van új is, ami azt jelenti, hogy .NET 4.0-ban két (perverzeknek akár) párhuzamosan használható object cache implementációt találhatunk. Hogy miért, arról a legviccesebb magyarázatként azt olvastam, hogy a régi az webre optimalizált, ami hát nekem laikusként oltári nagy hülyeségnek tűnik, valószínűleg egyszerűen a marketing ügyosztály szeretett volna mindenképp valamilyen jól hangzó választ kidolgozni arra a kérdésre, hogy na de mégis, miért??, és ennél jobb sehogy nem jutott eszükbe.
Inkább tippelnék arra, hogy az API-k annyira különböztek, hogy túlságosan sok kompromisszumot kellett volna megkötni a régi implementáció kidobásához, egy komolyabb breaking change behozása pedig nagyon nagy nyűg lenne azok számára, akik az eddigi cache implementációt használták. Ők pedig sokan vannak, ráadásul jellemzően nem is a a Pince 2000 Bt. kategória, inkább nagy forgalmú, komoly üzleti értéket képviselő portálok, ahol az üzemeltetés amúgy is könnyen agybuborékot kaphat az ötlet hallatán, hogy alattuk most cache implementációt fognak cserélni, de jobb lesz sokkal, esküszök.
Hogy jobb lesz-e vagy sem, arról ne higgyünk az égvilágon senkinek, próbáljuk ki inkább magunk. Hozzunk létre egy új konzol alkalmazást (vagy webest / WinFormsost, ami szívünkhöz közel áll), és referenciáljuk be a System.Runtime.Caching.dll-t. Ebben lakik az új cacheing. Using-oljuk be az azonos nevű névteret: ez alatt találjuk az új cache implemtáció, illetve API osztályait. Első körben érdemes egy pillantást vetni az ObjectCache osztályra: ez egy absztrakt oszály, amiből leszármazva saját cache implementációt készíthetünk. Kapunk pontosan egy darab ilyen implementációt is, a MemoryCache-t - ebből kedvünkre példányosíthatunk annyit per AppDomain, amennyit kedvünk tart, de ha nem akarunk semennyit, használjuk bátran a System.Runtime.Caching.MemoryCache.Default singletont. Itt egy Velocity-szerű API-val találkozhatunk, ami támogatja pl. a region-öket.
Mármint az API. A MemoryCache implementáció nem.
Vannak Add(), Get(), Remove() metódusok (ez nem túl meglepő), van Set() metódus (ha még nincs bent, berakja, ha bent van, update-el), illetve, ami nagyobbat változott, az a cache-beli elemek elavulásának kezelése. Minden elem mellé adhatunk egy CacheItemPolicy példányt, ami az adott elemhez tartozó "avulási szabályokat" reprezentálja. Property-ken keresztül szabályozhatjuk az abszolút- vagy csúszó elévülést, callback-eket adhatunk meg, amik meghívódnak, ha az adott elem elévül vagy frissítésre kerül, illetve a ChangeMonitors kollekcióba - micsoda meglepetés - change monitorokat tehetünk. Ez utóbbiak arra szolgálnak, hogy az adott elem cache-beli elévülését valamilyen külső körülményhez (filerendszerbeli file, SQL adatok, egy másik cache elem) megváltozásához kössük.

Az az igazság, hogy a cache nem az egyetlen olyan dolog, ami már a .NET 2-ben is gázos volt, és 4-ben ugyanúgy hagyták, ahogy volt.
VálaszTörlésMikre gondolsz?
VálaszTörlésItt azért csak félig-meddig van arról szó, hogy úgy hagyták. Úgy hagyták a régit, kompatibilitási megfontolásból, gondolom. Új feljlesztéseknél, vagy ha van elszántság portolni, használhatod az újat, szebbet, jobbat.
Több dolgot is felhozhatnék példának, de ha már a webes témánál vagyunk, akkor ott van a Global.asax és a HttpApplication körüli hekkelés. Tudtad például, hogy a framework reflection-nal keresi meg az Application_Start, Session_Start, stb. eventeket?
VálaszTörléshttp://devhawk.net/2009/08/06/I+Hate+Globalasax.aspx
http://aspnetresources.com/articles/event_handlers_in_global_asax.aspx