Toon posts:

[.NET 2.0] Attribute om static field direct te instantieren

Pagina: 1
Acties:

Verwijderd

Topicstarter
Als ik de volgende code heb in een ASP.NET 2.0 omgeving:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class SomeClass : BaseClass<DomainObject>
{
    // eenvoudige singleton implementatie:
    private static SomeClass _instance = new SomeClass();
    public static SomeClass GetInstance()
    {
        return _instance;
    }

    private SomeClass()
    {
     // voeg de instantie van deze class toe aan een collectie in een andere singleton
    }
}


Kan ik dan met een bepaalde .NET attribute forceren dat de _instance al wordt ge-instantieerd voordat ik deze daadwerkelijk aanroep in mijn code (SomeClass.GetInstance())? Het is eigenlijk de bedoeling dat alle objecten zoals bovenstaande zodra de web-applicatie initialiseert zichzelf instantieren en vanuit de constructor zichzelf meteen toevoegen aan de hierboven aangehaalde collectie in een andere singleton.

Alvast verschrikkelijk bedankt voor enige hulp, aangezien ik er hier behoorlijk op vast ben gelopen. :)

[ Voor 5% gewijzigd door Verwijderd op 25-04-2006 22:49 ]


  • Daspeed
  • Registratie: Maart 2001
  • Laatst online: 04:47
Kun je dat niet in de global.asax fixen?

  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

via een class/type constructor?
C#:
1
2
3
4
5
6
7
public class SomeClass
{
    private static SomeClass()
    {
      // wordt uitgevoerd zodra type geladen wordt
    }
}

We adore chaos because we like to restore order - M.C. Escher


Verwijderd

Topicstarter
DrClearbottom schreef op dinsdag 25 april 2006 @ 22:08:
Kun je dat niet in de global.asax fixen?
Dat zou op zich kunnen, maar ik laat de verantwoordelijkhed liever aan de objecten zelf over, zodat ik dat niet dubbel bij hoef te houden.

Verwijderd

Topicstarter
LordLarry schreef op dinsdag 25 april 2006 @ 22:10:
via een class/type constructor?
C#:
1
2
3
4
5
6
7
public class SomeClass
{
    private static SomeClass()
    {
      // wordt uitgevoerd zodra type geladen wordt
    }
}
Dat had ik al geprobeerd, maar hielp helaas niet (access modifiers kunnen overigens niet op static constructors).

  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Hoezo hielp het niet? Wordt die class/type constructor dan niet uitgevoerd?

We adore chaos because we like to restore order - M.C. Escher


  • Flard
  • Registratie: Februari 2001
  • Laatst online: 20-02 21:36
Ik weet niet hoeveel waarde je hecht aan het maken van een instantie, en wat je ermee wilt doen, maar je kunt een class ook de static modifier meegeven.

C#:
1
2
3
4
public static class SomeClass
{
//
}


Alles in zo'n klasse moet dan echter ook static zijn, maar je kunt dan wel een static constructor definiëren.

Verwijderd

Topicstarter
Flard schreef op dinsdag 25 april 2006 @ 22:29:
Ik weet niet hoeveel waarde je hecht aan het maken van een instantie, en wat je ermee wilt doen, maar je kunt een class ook de static modifier meegeven.
Alles in zo'n klasse moet dan echter ook static zijn, maar je kunt dan wel een static constructor definiëren.
dat kan helaas echter niet, omdat de klas overerft van een andere klasse. Dat was ik helemaal vergeten te vermelden, zal het in de startpost nog even erbij zetten.
LordLarry schreef op dinsdag 25 april 2006 @ 22:15:
Hoezo hielp het niet? Wordt die class/type constructor dan niet uitgevoerd?
Nope.

[ Voor 34% gewijzigd door Verwijderd op 25-04-2006 22:50 ]


  • MTWZZ
  • Registratie: Mei 2000
  • Laatst online: 13-08-2021

MTWZZ

One life, live it!

zoiets:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Foo {
    private static Foo Instance;
    public static Foo GetInstance() {
        if(Foo.Instance == null) {
            Foo.Instance = new Foo();
        }

        return Foo.Instance;
    }

    private Foo() {
        // Instantie meuk
    }
}


Maar zoals DrClearbottom al zegt dit is meer Global.asax werk

[ Voor 10% gewijzigd door MTWZZ op 25-04-2006 23:10 ]

Nu met Land Rover Series 3 en Defender 90


Verwijderd

Topicstarter
MTWZZ schreef op dinsdag 25 april 2006 @ 23:09:
zoiets:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Foo {
    private static Foo Instance;
    public static Foo GetInstance() {
        if(Foo.Instance == null) {
            Foo.Instance = new Foo();
        }

        return Foo.Instance;
    }

    private Foo() {
        // Instantie meuk
    }
}


Maar zoals DrClearbottom al zegt dit is meer Global.asax werk
Ik probeer de zaak juist niet te lazy loaden, maar zodra de applicatie initialiseert dit static field zo snel mogelijk te initialiseren. :)
Natuurlijk is het ook mogelijk met global.asax, alleen levert dat weer extra werk op, terwijl ik er vrij zeker van ben dat het attribuut wat ik zoek voorhanden is in het .NET framework (ben alleen de naam kwijt 8)7 ).

PS: Je initialiseert je singleton zo niet thread-safe! Zie ook http://www.yoda.arachsys.com/csharp/singleton.html.

[ Voor 3% gewijzigd door Verwijderd op 25-04-2006 23:48 ]


  • Flard
  • Registratie: Februari 2001
  • Laatst online: 20-02 21:36
Ik bedenk me eigenlijk dat als je al een static constructor zou maken in een niet-static class, dat die constructor dan toch pas zou worden uitgevoerd nadat je de eerste keer iets aanroept bij de betreffende klasse (JIT Compile?).

In zo'n geval zul je dus altijd eerst iets bij die static-class moeten aanroepen zodat die Instance alvast gevuld is. Daar het niet van binnenuit de class gaat, zul je het van buitenaf moeten doen, wat dan inderdaad een global.asax.

Ik heb net even globaal MSDN doorgebladerd, maar ik kon zo geen Attribute vinden voor zoiets, maar ben wel benieuwd of het dan gaat, en hoe het dan werkt...

  • MTWZZ
  • Registratie: Mei 2000
  • Laatst online: 13-08-2021

MTWZZ

One life, live it!

Verwijderd schreef op dinsdag 25 april 2006 @ 23:19:
Ik probeer de zaak juist niet te lazy loaden, maar zodra de applicatie initialiseert dit static field zo snel mogelijk te initialiseren. :)
Ah op die fiets maar dan zou ik de moeite nemen om global.asax te gebruiken.
Natuurlijk is het ook mogelijk met global.asax, alleen levert dat weer extra werk op, terwijl ik er vrij zeker van ben dat het attribuut wat ik zoek voorhanden is in het .NET framework (ben alleen de naam kwijt 8)7 ).
Ik ben aan het graven geweest maar ik kan niet echt iets vinden wat in die richting wijst
PS: Je initialiseert je singleton zo niet thread-safe!
weet ik, het was ook maar een brainfart :)

Nu met Land Rover Series 3 en Defender 90


  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

eventueel kun je dit doen:

XML:
1
2
3
4
<loadTypes>
  <type>MyProject.SomeClass, MyProject</type>
  <type>MyProject.SomeClass2, MyProject</type>
</loadTypes>


en

C#:
1
2
3
4
5
6
// in je global.asax:
// uitlezen loadTypes
foreach (Type t in loadTypes)
{
    t.GetMethod("GetInstance", Type.EmptyTypes, static | public).Invoke(null); // snel uit het hoofd
}


eventueel kun je in je xml file ook de methodenaam nog aangeven moest je deze niet vast hebben.

Dit is natuurlijk de vereenvouding van:
C#:
1
2
3
// in global.asax:
SomeClass.GetInstance();
SomeClass2.GetInstance();

in die zin dat eentje vergeten niet meteen je hele app laat recompilen want afaik is dat je grootste struikelblok.


gevonden: (log4net gebruikt dit ook om de configuratie zo snel mogelijk op orde te krijgen)
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
[AttributeUsage(AttributeTargets.Assembly)]
class SomeClassLoader : Attribute
{
   public SomeClassLoader() { SomeClass.GetInstance(); }
}

// verder:

[assembly: SomeClassLoader()]
class SomeClass
{
 //...
}

[ Voor 23% gewijzigd door H!GHGuY op 26-04-2006 09:52 ]

ASSUME makes an ASS out of U and ME


Verwijderd

Topicstarter
HIGHGuY schreef op woensdag 26 april 2006 @ 09:40:

gevonden: (log4net gebruikt dit ook om de configuratie zo snel mogelijk op orde te krijgen)
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
[AttributeUsage(AttributeTargets.Assembly)]
class SomeClassLoader : Attribute
{
   public SomeClassLoader() { SomeClass.GetInstance(); }
}

// verder:

[assembly: SomeClassLoader()]
class SomeClass
{
 //...
}
Zoiets bedoelde ik, bedankt! :)

  • EfBe
  • Registratie: Januari 2000
  • Niet online
Allereerst even een reactie op die attribute hack: niet gebruiken, want je code wordt onbeheerbaar, daar je acties doet via een attribute die je niet verwacht wanneer je de code leest.
Verwijderd schreef op dinsdag 25 april 2006 @ 21:55:
Als ik de volgende code heb in een ASP.NET 2.0 omgeving:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class SomeClass : BaseClass<DomainObject>
{
    // eenvoudige singleton implementatie:
    private static SomeClass _instance = new SomeClass();
    public static SomeClass GetInstance()
    {
        return _instance;
    }

    private SomeClass()
    {
     // voeg de instantie van deze class toe aan een collectie in een andere singleton
    }
}


Kan ik dan met een bepaalde .NET attribute forceren dat de _instance al wordt ge-instantieerd voordat ik deze daadwerkelijk aanroep in mijn code (SomeClass.GetInstance())? Het is eigenlijk de bedoeling dat alle objecten zoals bovenstaande zodra de web-applicatie initialiseert zichzelf instantieren en vanuit de constructor zichzelf meteen toevoegen aan de hierboven aangehaalde collectie in een andere singleton.

Alvast verschrikkelijk bedankt voor enige hulp, aangezien ik er hier behoorlijk op vast ben gelopen. :)
Hier kijken:
http://www.yoda.arachsys.com/csharp/singleton.html
dan doen wat Jon daar zegt en die ranzige attribute hack links laten liggen.

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


Verwijderd

Topicstarter
EfBe schreef op woensdag 26 april 2006 @ 14:07:
Allereerst even een reactie op die attribute hack: niet gebruiken, want je code wordt onbeheerbaar, daar je acties doet via een attribute die je niet verwacht wanneer je de code leest.
[...]
Hier kijken:
http://www.yoda.arachsys.com/csharp/singleton.html
dan doen wat Jon daar zegt en die ranzige attribute hack links laten liggen.
Point taken.
Probleem met die static variabelen is dat ze te lazy instantieren. Ze zouden eigenlijk, wanneer de applicatie opstart, zo snel mogelijk moeten worden ge-instantieerd. En dan het liefst zonder dat ik deze klasse daarvoor expliciet eerst ergens anders moet aanroepen, want er komen nog een paar van dit soort klassen bij.

  • Flard
  • Registratie: Februari 2001
  • Laatst online: 20-02 21:36
Dan kun je wellicht nog beter een eigen interface kunnen maken, en dan in je startupcode kijken welke klassen deze interface implenteren. In die interface staat dan bijvoorbeeld alleen de get voor een Instance (een property dus), en die roep je dan aan in je startup.
Dan heb je het volledig in eigen hand, en naar mijn mening zonder ranzige hacks...

(Je zou enkel nog kunnen twisten over het feit of je een interface of een attribuut moet gebruiken)

  • EfBe
  • Registratie: Januari 2000
  • Niet online
Verwijderd schreef op woensdag 26 april 2006 @ 22:27:
[...]
Point taken.
Probleem met die static variabelen is dat ze te lazy instantieren. Ze zouden eigenlijk, wanneer de applicatie opstart, zo snel mogelijk moeten worden ge-instantieerd. En dan het liefst zonder dat ik deze klasse daarvoor expliciet eerst ergens anders moet aanroepen, want er komen nog een paar van dit soort klassen bij.
Ik zie niet echt waarom dit een probleem is. De statics worden geinitialiseerd voordat ze worden gebruikt, dus t.a.t. heb jij een instance at runtime. Wanneer dat initialiseren gebeurt heb je niet in de hand, maar dat is wel met meer zo. Maak maar eens een docked form met 5 grids er op en laadt dat maar at runtime. Kun je ook 5 seconden wachten totdat die assemblies geladen zijn en de JIT ze opgevroten heeft. Daar doe je weinig aan.

Als jij die statics niet gebruikt, dan hoef je toch ook geen initialisatie aan het begin? Je roept ze dus aan, dus krijg je een init slag aan het begin.

[ Voor 11% gewijzigd door EfBe op 27-04-2006 09:42 ]

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

EfBe schreef op woensdag 26 april 2006 @ 14:07:
Allereerst even een reactie op die attribute hack: niet gebruiken, want je code wordt onbeheerbaar, daar je acties doet via een attribute die je niet verwacht wanneer je de code leest.


[...]

Hier kijken:
http://www.yoda.arachsys.com/csharp/singleton.html
dan doen wat Jon daar zegt en die ranzige attribute hack links laten liggen.
in dit geval vind ik deze attribute hack helemaal zo erg nog niet.

Het is niet alsof het programma breekt als de attribute niet aanwezig is. Het is enkel een performance optimalisatie.
Bovendien kan je je API zelf zo maken dat je bijvoorbeeld de programmeur (waarschijnlijk hijzelf in dit geval) aanspoort om dit attribuut als de assembly gereferencet wordt net boven de static void Main te schrijven of wanneer er geen reference is, deze zelf net boven de klasse te laten staan.

Bovendien ben je helemaal zeker van je stuk als je deze net boven de klasse laat staan dat alles op het juiste moment (namelijk bij inladen van de assembly) klaar staat. Daar heeft geen enkele andere externe assembly/code/... nog vat op.

ASSUME makes an ASS out of U and ME


Verwijderd

Topicstarter
EfBe schreef op donderdag 27 april 2006 @ 09:40:
[...]

Ik zie niet echt waarom dit een probleem is. De statics worden geinitialiseerd voordat ze worden gebruikt, dus t.a.t. heb jij een instance at runtime. Wanneer dat initialiseren gebeurt heb je niet in de hand, maar dat is wel met meer zo. Maak maar eens een docked form met 5 grids er op en laadt dat maar at runtime. Kun je ook 5 seconden wachten totdat die assemblies geladen zijn en de JIT ze opgevroten heeft. Daar doe je weinig aan.

Als jij die statics niet gebruikt, dan hoef je toch ook geen initialisatie aan het begin? Je roept ze dus aan, dus krijg je een init slag aan het begin.
Het gaat erom dat in de constructor van die class de singleton instance (1) wordt toegevoegd aan een (dictionary) collection in een andere singleton class (2) (reeds gecompileerd). Bepaalde functies maken vervolgens weer gebruik van die collectie in die singleton (2). Om te zorgen dat die functies goed kunnen werken is het van belang dat die collectie van meet af aan "volledig" is; daarom is het een probleem. Tuurlijk kan ik de GetInstance()'s voor al die classes wel gaan aanroepen in een global.asax functie, maar dat voelt zo dubbelop (en creeert flinke mogelijke valkuil voor onderhoudswerkzaamheden aan dat deel van de applicatie).

[ Voor 8% gewijzigd door Verwijderd op 28-04-2006 01:10 ]


  • EfBe
  • Registratie: Januari 2000
  • Niet online
Verwijderd schreef op vrijdag 28 april 2006 @ 01:09:
[...]


Het gaat erom dat in de constructor van die class de singleton instance (1) wordt toegevoegd aan een (dictionary) collection in een andere singleton class (2) (reeds gecompileerd). Bepaalde functies maken vervolgens weer gebruik van die collectie in die singleton (2). Om te zorgen dat die functies goed kunnen werken is het van belang dat die collectie van meet af aan "volledig" is; daarom is het een probleem. Tuurlijk kan ik de GetInstance()'s voor al die classes wel gaan aanroepen in een global.asax functie, maar dat voelt zo dubbelop (en creeert flinke mogelijke valkuil voor onderhoudswerkzaamheden aan dat deel van de applicatie).
Als je instance A in de collection van singleton B wil stoppen dan werkt dat, als jij daarna dan B's collection wilt gebruiken, dan is die er, want dat garandeert die static initialisation en static constructor.

Als het waar zou zijn wat jij zegt, zou je dus kunnen hebben dat non-static code eerder runt dan de static constructor/initializer van de types die de non-static code gebruikt. Lijkt me niet mogelijk. :)

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com

Pagina: 1