Newsgroup: it.comp.www.asp
Titolo: [ASP.NET] dubbio amletico sul life cycle di una classe istanziata in un modulo

ok il titolo è già assurdo di per se, spero che non lo sia altrettanto il
resto :-)
Sto riprogettando il mio portale in 
ASP.NET
 e XHTML (e gia solo per renderlo
XHTML compliant c'è un bel po' da sudare)
Il mio dubbio consiste in questo: sto progettando il sito in modo che si
possano generare menu dinamici in base all'area ma in modo object oriented
(attualmente gia lo fa ma trattandosi di ASP puro avevo semplicemente fatto
una sfilza di Case IDAreaXYZ, etc...
La soluzione che ho pensato è stata quella di crearmi una classe AreaSito
nella quale definire una Struct contenente i parametri che identificano
un'area, compreso di voci di menu, etc... e di leggerne i valori da un file
xml e, dato che gli ID area non sono lineari (nel senso che ci potrebbero
essere buchi) ho optato poi per creare una Collection piena di Struct
conteneti le mie specifiche di ogni singola area (quindi non ho usato Array)
ma questo è un dettaglio.
Il punto è questo: per ottimizzare la cosa, volevo ovviamente leggere il
file XML solo una volta dato che non cambierà (o per lo meno non sovente,
nel qual caso avrei comunque una pagina di amministrazione dalla quale
"rigenerare" il tutto) e per farlo ho pensato di lanciare l'inizializzazione
della classe durante l'Application_Start nel Global.asax.
Mentre sviluppavo, trascinato dall'abitudine di sviluppare applicativi
client/server più che siti WEB, ho dichiarato una variabile AreaSito in un
modulo globale, per aver accesso da qualsiasi pagina al mio oggetto, che
secondo la mia idea doveva essere per l'appunto condiviso da ogni utente.
In ASP ciò si poteva fare dichiarando nel global.asa l'oggetto che volevamo
condividere, ma in 
ASP.NET
, da quel che ho visto, si può ottenere lo stesso
effetto istanziando l'oggetto in un modulo globale, confermate questa
cosa???
Schematizzando, la mia situazione è quindi questa:
ho una classe AreaSito dichiarata pressappoco così
Public Class cAreeSito
   Public Structure structAreaSito
      Dim IDArea As Integer
      Dim NomeArea As String
      Dim VoceMenuArea As String
      Public Sub SetArea(ByVal ID_Area As Integer, ByVal sNomeArea As
String, ByVal sVoceMenuArea As String, ByVal bLinkPubblico As Boolean)
         IDArea = ID_Area
         NomeArea = sNomeArea
         VoceMenuArea = sVoceMenuArea
      End Sub
   End Structure
   Public collAreeSito As Collection
   Public Sub InizializzaAree()
      ...... qui inizializzo la classe caricando i dati dal file xml e
riempiendo la collection collAreeSito
   End Sub
End Class
in un modulo che ho chiamato IstanzeGlobali.vb, ho dichiarato:
Public AreaSito as New cAreeSito
nel global.asax invece c'è:
Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
   AreeSito.InizializzaAree() 'inizializzo la classe cAreeSito
End Sub
A questo punto, ricordandomi come funzionava ASP (anche se ignoravo/ignoro
come vengano considerati i moduli in 
ASP.NET
, anche se ora qualche idea ce
l'ho) mi sarei aspettato un errore dato che poi ho pensato: non è che
facendo così, dato che credo che il modulo sia visibile solo nel contesto
del singolo utente e quindi istanziato ad ogni esecuzione di una pagina, mi
verrà fuori un errore dicendo che la collection non è impostata? (ricordo
che la imposto solo nell'application_onstart)
E invece con mia sorpresa tutto ha funzionato benissimo, ho per scrupolo
inserito come debug una stringa nella pagina HTML che si vedeva solo se
veniva eseguito il metodo InizializzaAree e notavo che quella stringa
compariva solo per l'appunto quando restartava la mia applicazione, dunque
sono arrivato alla conclusione che ciò che si dichiara in un modulo, ha una
visibilità che dura per tutta la durata dell'applicazione, cosa molto comoda
in effetti, ma che non mi sarei aspettato. Sono giunto ad una giusta
conclusione o ho preso un abbaglio? (nel qual caso saprebbe più di bug però,
perchè debug alla mano la funzione di inizializzazione viene lanciata solo 1
volta all'avvio dell'app. e poi basta, quindi...)
Scusate per il post lunghetto ma volevo descrivere bene la situazione così
che magari possiate riprodurla (ovviamente dovete poi usare, in un webform,
l'oggetto dichiarato nel modulo globale per la prova del 9)
ciao
-- 
Fabio Angela (aka Red Angel)
cerchi consigli per un hosting? 
http://hosting.redangel.it
http://www.redangel.it
 - il portale sulla programmazione

 Fabio Angela (aka Red Angel)
Ciao
--
AZ [Microsoft .NET MVP]

 cosa???
Gli oggetti Application di 
ASP.NET
 sono condivisi nelle singole istanze 
dell'applicazione, cioé c'è un oggetto Application diverso per ogni 
macchina e per ogni application domain.
ASP.NET
 può utilizzare più application domain per ogni applicazione, lo 
fa periodicamente per "riciclare" i vecchi application domain -- ciò 
contribuisce a ridurre le probabilità di memory leak.
In pratica, l'oggetto Application è indicato per dati globali, condivisi 
da tutta l'applicazione e (generalmente) a sola lettura. Proprio quello 
che vorresti fare tu.
Ci sono alcune controindicazioni nell'usare l'oggetto Application.
Come descritto sopra, 
ASP.NET
 sostituisce periodicamente gli application 
domain; pertanto lo stato memorizzato nell'oggetto Application non è 
durevole, è necessario - come hai fatto in Application_Start - 
ripristinarlo se questo viene perso.
Gli oggetti in Application non vengono liberati dalla memoria per lungo 
tempo. E' importante pertanto che siano oggetti di uso frequente e di 
dimensioni ridotte, in caso contrario è meglio usare il data caching che 
consente di liberare gli oggetti ove fosse necessaria più memoria.
Poiché Application è un oggetto globale, gli aggiornamenti di tale 
oggetto devono essere protetti usando i metodi Lock ed Unlock. Ciò 
favorisce un uso a sola lettura, poiché un semaforo globale condiviso e 
molto richiesto è un grande freno alla scalabilità ed alle performance 
dell'applicazione.
Come già datto, l'oggetto Application non è condiviso fra più 
application domain -- pertanto il suo uso è limitato se si ha 
disposizione una batterie di servers (web farm).
-- 
Roberto Lupi

 AZ [Microsoft .NET MVP]
ciao e grazie per la confermao, ora posto però un altro quesito che ieri mi
ha fatto perdere un bel po' di tempo :-)
-- 
Fabio Angela (aka Red Angel)


 Fabio Angela (aka Red Angel)
Ciao
