Gå til innhold

bruk av SINGLETON i WEB apps i stedet for session variabler


Anbefalte innlegg

FOlkens.. Jeg har følgende problemstilling...

 

Jeg har et stort klassebibliotek som vi bruker i våre Windows applikasjoner. I disse klassesettene bruker jeg singleton klasser over en lav sko for å "globalisere" ting. Eksempelvis er RegistryManager og SecurityManager slike klasser, dette fordi alle objekter skal kunen spørre i disse uten at de må kjenne til noe referanser og slikt.

 

Nå skal vi derimot igang med å lage web versjoner av enkle funksjoner av våre aplikasjoner og da kom jeg til å tenke på at en static class kan være problematisk fordi den blir super global og alle brukere av web siden deler denne og det er ikek ønskelig i forbindelse med slikt som registry og security.

 

Så spørsmålet er derfor:

Hvordan vil følgende klasse oppføre seg i web sammenheng:

 

public sealed class SecurityManager
{
 private static volitile SecurityManager instance;
 private static object synchRoot = new Object();
 private SecurityManager(){}
 public static SecurityManager Instance
 {
   get
   {
     if (instance == null)
       lock (synchRoot)
         if (instance == null)
           instance = new SecurityManager();
     return instance;
   }
 }
}

Som dere ser ut av dette så er jo ikke objektet static på samme måte som en static class. Kan jeg derfor bruke dette som et "static for current user" object ?

His ikke, er det en måte å implementere dette slik at den kan brukes på tvers av WEB dokumenter ?

Lenke til kommentar
Videoannonse
Annonse

Men vil det funke i Windows miljøet da? Jegt vil jo ikke at det skal instanseres flere versjoner av disse klassene for hver tråd jeg måtte finne på å starte opp..

Neppe. Ettersom hver tråd vil ha en unik SecurityManager. Du må isåfall ha en måte å finne ut hvilken bruker det er snakk om. Tror ikke det finnes en løsning som kan brukes begge steder av seg selv.

 

Personlig synes jeg ikke spesielt mye om singleton mønsteret, jeg foretrekker å heller lage instanser og dele dem ut til de delene som trenger det fremfor statiske variabler og singletons, men det kommer vel an på hva en trenger tipper jeg.

Lenke til kommentar

Blir ikek det mye å håndtere hele tiden da? Eller samler du dette i en GlobalClass eller noe slikt da og sender denne der hvor den er nødvendig?

 

I så fall - hva er fordelen med dette? Jeg ser jo fordelen i forbindelse med WEB bruk for da kan den jo bare sendes som en session variabel... Må tenke litt nøye på dette...

 

Takker for svar

Lenke til kommentar

Jeg driver ikke med webutvikling, så jeg er ikke kanskje den beste til å svare på dette.

Kan du bruke en Dictionary<int, SecurityManager> (hvor int er session id) for å lagre det kanskje? Så kan den bare hoppe over den delen hvis den (på et eller annet vis) vet at det ikke er en webtjeneste.

 

edit: et problem som jeg tenkte på med en gang er opprydning... kan du ikke lagre objektet i session? Altså

 

get
{
 if(!session.ContainsKey("SecurityManager"))
   session.Add("SecurityManager", new SecurityManager);
 return session["SecurityManager"];
}

Endret av GeirGrusom
Lenke til kommentar
  • 2 uker senere...

Blir ikek det mye å håndtere hele tiden da?

Det er derfor Dependency Injection Frameworks er så populære - de gjør det for deg. Ta en titt på StructureMap, Unity, eller min favoritt Ninject.

 

I så fall - hva er fordelen med dette?

Fordelenen ved Dependency Injection (altså at man gir avhengighetene til objektene i stedet for at de henter dem selv) er at man får mindre koblet kode. Slik kode er enklere å holde orden på, enklere å teste, enklere å holde bugfri rett og slett. Globale variabler (som Singleton Pattern er en fasilitator for) er som regel en uting - i alle fall om det brukes i stor utstrekning.

Endret av torbjørn marø
Lenke til kommentar

Ok. Skjønnte ikke noe når du begynnte å snakke om Dependency Injectons og slikt så dermed var det på tide å "sjekke fakta"

 

Så vidt jeg skjønner så handler dette egentlig bare om en bred bruk av Interfaces. Enten man snakker om Constructor injections eller Setter injectons. Resultatet er jo det samme.

 

Men om dette gir noe bedre resultat enn å ha singleton klasser er jeg usikker på. Men det er jo selvsagt mulig aqt jeg tar feil her. Jeg ser jo fordelen av å bruke interfaces. Da bestemmer man jo kontrakten slik at andre objekter kan snakke med de globale managerene uten å behøve å kjenne til dem. Egentlig ligner dette veldig på måten jeg kodet på før jeg oppdaget Singleton. Da hadde jeg jo en global manager om du vill, som instanserte det som var nødvendig. Når noe ble kallt opp, enten det var en FORM, en WEB side eller en eller annen form for worker, så sendte jeg bare inn et interface, og i noten tilfeller i min spede barnom så sendte jeg hele objektet (jada, gjør ikek det lenger med mindre det er absolutt nødvendig ;-)) I bunn og grunn ligner jo dette vledig på dependency injecton da.

 

Grunnen til at jeg fallt sånn for SIngleton var jo at jeg veldig enkelt kunen slenge op noe globale manager objekter, som EntityManager, SecurityManager, SQLConnectionManager, RegistryManager, RepositoryManger og sist, men ikke minst, en System Manager.

 

Det var veldig enkelt å bare gjøre disse til Singleton og vips så trenge jeg aldri mere bekymre meg om de var instansert elelr iikke. I tillegg ligger de på et globalt plan og er således tilgjengelig for absolutt alle komponenter i hele solutionen, og de instanserer jo seg selv ved første touch - uavhengig av hvem som toucher.

 

Ulempen, sånn jeg ser det umiddelbart er jo at alt må endres og rekompilleres hvis en prototype endrer seg. Det er jeg forsåvidt inneforstått med..... Men jeg så liksom det "enkle" i det singleton greiene..

 

Vel, tror kansje jeg må revurdere litt.

Lenke til kommentar
  • 4 uker senere...

Det er i det minste én tråd for hver bruker, så hvis du legger til [ThreadStatic] så burde det vel funke?

Leste denne først nå, og er ganske sikkert på at dette ville være lite lurt, så tenkte jeg burde si fra (burde begynne å lese hele diskusjonene før jeg blander meg inn). Trådene er nemlig ikke "sticky", en bruker beholder ikke samme tråden fra request til request, og deles derfor mellom alle som bruker siten.

 

State/tilstand er generelt sett noe man forsøker å holde seg unna i webløsninger. Har du absolutt behov for state som holdes på server pr bruker mellom requests så er session state i praksis din "eneste" løsning.

 

Jeg hadde samme problem som HDSoftware for noen år tilbake, hvor jeg trengte å dele singleton-klassene mellom WinForms-klient og ASP.NET-løsning. Endte da opp med å ha kode i singleton-klassene som sjekket om de levde i en web kontekst, og "lagret seg selv" anderledes da.

 

Noe ala å sjekke om HttpContext.Current er ulik null, for så å sette/hente instansen fra HttpContext.Current.Session i stedet for en static variabel.

 

Det fungerte, men har i ettertid lært å designe løsningene mine slik at dette ikke er nødvendig (Singletons er en uting).

Lenke til kommentar
  • 1 måned senere...

Slenger meg på her og vil også anbefale en DI container som Torbjørn gjør her. Da vil etterhvert få kode som relativt sømløst kan brukes på web og win. Når det er sagt, så må du likevel ha litt kontroll på hva du driver med om du kjører en binding til InSingletonScope med en DI container. Det kan få uante konsekvenser om du ikke passer deg. Ninject har forøvrig noe de kaller InRequestScope som kanskje er mer interessant for deg

Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
×
×
  • Opprett ny...