[C#] Singleton is na laden via reflection geen singleton

Pagina: 1
Acties:

  • Martkrui
  • Registratie: Februari 2002
  • Laatst online: 13-05 22:28
Ik loop tegen het volgende probleem op:

In een regel: Mbv reflection kan je een singleton meerdere malen instantieren. terwijl ik dit juist niet wil

Mijn prog moet een aantal eigen geschreven "handlers" laden via reflection. Dit werkt nog prima. Maar een van die handlers gebruikt de modem (via com1). Hiervoor is een singleton modemclass geschreven. die zorg dat maar een iemand tegelijk de modem kan gebruiken.
(dus reflection instantieer object HandlerA dat singleton Modem gebruikt)

Probleem is dat bij het laden mbv reflection de singleton twee keer geinstantieerd word. (of zo vaak als ik het HanderA via reflection maar instantieer). Dit kan ik zien mbv de logging en door exceptions die dan optreden.

Waarom niet gewoon kijken of com1 bezet is ? Modem houd de verbinding open om zo volgende requests sneller af te handelen.

Mijn vragen : Is iemand dit probleem al eens tegen gekomen ?
Heeft iemand tips in welke richting ik de oplossing kan zoeken ?

I haven't lost my mind! It's backed up on tape somewhere!


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Onder java is er aan de serialize interface een extra methode toegevoegd waarmee je zelf kunt bepalen welk object terug gestuurd gaat worden bij de deserialisatie. Deze methode kan door singletons gebruikt worden om de 'echte' singleton terug te sturen ipv de geserializde versie. Kan c# niet zoiets?

Verder worden singletons vaak ten onrechte gebruikt en kunnen veel problemen veroorzaken (oa allerlei onnodige dependencies)

Verwijderd

ik heb geen verstand van c#, maar kan je niet zoiets doen als:

code:
1
2
3
4
5
6
7
8
9
10
11
class Foo{

private static Foo foo = new Foo();

private Foo(){}

  public static Foo instanceOff(){
     return foo;
   }

}

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Verwijderd schreef op 20 september 2004 @ 16:48:
ik heb geen verstand van c#, maar kan je niet zoiets doen als:

code:
1
2
3
4
5
6
7
8
9
10
11
class Foo{

private static Foo foo = new Foo();

private Foo(){}

  public static Foo instanceOff(){
     return foo;
   }

}
Lees zijn bericht nou even goed. Hij wil niet weten hoe je een singleton kan maken, hij wilt verhinderen dat een singleton die gedeserialized wordt niet een andere instantie gaat worden dan de 'echte' singleton. Dit is een bekend probleem bij de combinatie singleton/serializen.

  • Martkrui
  • Registratie: Februari 2002
  • Laatst online: 13-05 22:28
Op zich werkt de singleton prima. Hij is zelfs thread safe:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private MSing()
{
    //Hier wat init
}

public static MSing GetMSing()
{

    lock (padlock)
    {   
        if( Instance == null )
        {
            Instance = new MSing();
        }
    }
    return( Instance );
}


Maar het is juist de combinatie met het laden via reflection die het singleton idee omzeep helpt

I haven't lost my mind! It's backed up on tape somewhere!


  • whoami
  • Registratie: December 2000
  • Laatst online: 16:52
Alarmnummer schreef op 20 september 2004 @ 16:47:
Onder java is er aan de serialize interface een extra methode toegevoegd waarmee je zelf kunt bepalen welk object terug gestuurd gaat worden bij de deserialisatie.
In .NET kan je serializing op 2 manieren implementeren:
- gewoon het [Serialize] attribute toepassen: op die manier worden alle public properties geserialized.
- de ISerializable interface implementeren waarbij je zelf opgeeft wat er moet geserializeerd worden, en hoe er gedeserialized moet worden.

https://fgheysels.github.io/


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

whoami schreef op 20 september 2004 @ 16:52:
[...]

In .NET kan je serializing op 2 manieren implementeren:
- gewoon het [Serialize] attribute toepassen: op die manier worden alle public properties geserialized.
- de ISerializable interface implementeren waarbij je zelf opgeeft wat er moet geserializeerd worden, en hoe er gedeserialized moet worden.
Maar kan je ook opgeven welk object terug gestuurd gaat worden bij het deserializen?

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Elvis implements Serializable{
    public static final Elvis INSTANCE = new Elvis();

    private Elvis() {
        ...
    }

   private Object readResolve() throws ObjectStreamException {
    // Return the one true Elvis and let the garbage collector
    // take care of the Elvis impersonator.
    return INSTANCE;
}
}


[edit]
*Alarmnummer wrijft de stront ff uit zijn ogen... het gaat over reflectie.. niet serialisatie*

[ Voor 6% gewijzigd door Alarmnummer op 20-09-2004 16:58 ]


  • whoami
  • Registratie: December 2000
  • Laatst online: 16:52
Dr.DNA schreef op 20 september 2004 @ 16:52:
Op zich werkt de singleton prima. Hij is zelfs thread safe:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private MSing()
{
    //Hier wat init
}

public static MSing GetMSing()
{

    lock (padlock)
    {   
        if( Instance == null )
        {
            Instance = new MSing();
        }
    }
    return( Instance );
}


Maar het is juist de combinatie met het laden via reflection die het singleton idee omzeep helpt
Hoe laad je die singleton dan , of hoe creeër je die singleton ?
Gebruik je een MethodInvoke op de GetInstance method ?

https://fgheysels.github.io/


  • Martkrui
  • Registratie: Februari 2002
  • Laatst online: 13-05 22:28
Ik laad via Reflection HandlerA. mbv Activator.CreateInstance( type );

HandlerA heeft in zijn init staan : localMSing = MSing.GetMSing();

-- edit- -

Dit is dus ongeveer war Macros ook zei. Een soort wrapper om de singleton.

[ Voor 25% gewijzigd door Martkrui op 20-09-2004 17:22 ]

I haven't lost my mind! It's backed up on tape somewhere!


  • Macros
  • Registratie: Februari 2000
  • Laatst online: 30-04 09:28

Macros

I'm watching...

De reflection aanroep gebruikt toch de constructor. Kan je die constructor niet zo aanpassen dat als er al een instance is dat hij een exception opgooit?
Of je moet een wrapper object maken. Dus dat je meerdere instanties maakt dmv. reflectie, maar die gebruiken intern de singleton.

"Beauty is the ultimate defence against complexity." David Gelernter


  • whoami
  • Registratie: December 2000
  • Laatst online: 16:52
Hmm,....
Als je iets gaat gaan instantieren dmv reflection, dan heb je de mogelijkheid om te specifieren dat de private constructor moet gebruikt worden. Op die manier omzeil je natuurlijk je Singleton eigenschappen.
Echter, ik zie nergens dat je dat specifieert, en aangezien je blijkbaar ook geen andere constructor hebt, zou die code imho een exceptie moeten gooien (constructor not found oid).

Ik denk gewoon dat je je singleton niet mag creeëren via reflection; waarom zou je dat eigenlijk willen doen?

Of misschien kan je het eens zo proberen:
code:
1
2
MethodInfo mi = typeof(MySingletonClass).GetMethod ("GetInstance", BindingFlags.Static);
MySingletonClass singleObj = mi.Invoke (null, BindingFlags.Static, null, null, null);

Op die manier ga je dus de 'GetInstance' method gaan ophalen van je singleton class, en ga je die gaan uitvoeren.
Ik heb het niet getest, de code is gewoon uit de losse hand.

https://fgheysels.github.io/


  • EfBe
  • Registratie: Januari 2000
  • Niet online
Je kunt alleen met een static constructor iets doen, al het andere is te omzeilen middels reflection en aanverwante grappen en grollen. En anders maak je een nieuw appDomain en laad je vrolijk je 2e singleton daarin...

Ergo: het gaat tot een bepaald moment goed, daarna, wanneer mensen middels low level kunstgrepen bepaalde dingen gaan doen, hou je het niet tegen. Ik bedoel: 1 regel code is genoeg om een private member van een willekeurig object te lezen OF te schrijven. Dus tegenhouden doe je zoiets niet. Hooguit kun je een lock op een externe resource proberen te maken in je code, waardoor meerdere keren de code opstarten niet werkt, ook niet in een ander appDomain.

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


  • whoami
  • Registratie: December 2000
  • Laatst online: 16:52
EfBe schreef op 20 september 2004 @ 19:19:

Ergo: het gaat tot een bepaald moment goed, daarna, wanneer mensen middels low level kunstgrepen bepaalde dingen gaan doen, hou je het niet tegen. Ik bedoel: 1 regel code is genoeg om een private member van een willekeurig object te lezen OF te schrijven. Dus tegenhouden doe je zoiets niet. Hooguit kun je een lock op een externe resource proberen te maken in je code, waardoor meerdere keren de code opstarten niet werkt, ook niet in een ander appDomain.
Met behulp van reflection kan je idd private members/method gaan callen, maar dit kan je eigenlijk verhinderen door dmv een StrongNameIdentityPermission attribute te gaan definieren voor die private members/methods.

Toch blijf ik het geen goed idee vinden om dmv reflection die singleton te gaan accessen (tenzij je er een hele goeie reden voor hebt).

https://fgheysels.github.io/


  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
EfBe schreef op 20 september 2004 @ 19:19:
[...]
Ergo: het gaat tot een bepaald moment goed, daarna, wanneer mensen middels low level kunstgrepen bepaalde dingen gaan doen, hou je het niet tegen. Ik bedoel: 1 regel code is genoeg om een private member van een willekeurig object te lezen OF te schrijven. Dus tegenhouden doe je zoiets niet. [...]
Maar ik zou het ook niet willen tegenhouden.
Ik bedoel, accessmodifiers zijn er om het programmeren makkelijker te maken, om implementaties af te schermen en om een gecontroleerde access tot de data mogelijk te maken.
Als iemand dat willens en wetens gaat slopen met concepten als reflection, fine with me. Ik kan dan geen garanties meer geven over de staat van het object, dus dan mag diegene het ook lekker zelf uitzoeken ;) Waarschijnlijk ben je sneller en beter klaar als je gewoon een subclass schrijft :)
Maarja dat is een beetje offtopic, sorry :)

  • Infinitive
  • Registratie: Maart 2001
  • Laatst online: 25-09-2023
Trouwens, rommelen met private members via reflection heeft nog een nadeel: als je de applicatie deployed via het web (one touch deployment), dan keert het security mechanisme zich tegen je. Je mag alleen public members "invoken" (mmm. "uitvoeren" in het Nederlands dekt deze term niet volledig...).

putStr $ map (x -> chr $ round $ 21/2 * x^3 - 92 * x^2 + 503/2 * x - 105) [1..4]


  • whoami
  • Registratie: December 2000
  • Laatst online: 16:52
Infinitive schreef op 20 september 2004 @ 21:25:
Trouwens, rommelen met private members via reflection heeft nog een nadeel: als je de applicatie deployed via het web (one touch deployment), dan keert het security mechanisme zich tegen je. Je mag alleen public members "invoken" (mmm. "uitvoeren" in het Nederlands dekt deze term niet volledig...).
Dat is toch geen nadeel? Het is gewoon de bedoeling niet dat je private members rechtstreeks aanspreekt. (En dat kan je dus ook verhinderen dmv het StrongNameIdentittyPermission attribute.
(Maar goed, als je een admin bent, kan je er dan ook weer zorgen dat die code-access security uitgeschakeld wordt, etc..... ).

https://fgheysels.github.io/


  • Martkrui
  • Registratie: Februari 2002
  • Laatst online: 13-05 22:28
Maar ik laad de singleton niet direct.

Ik laad een object (HandlerA) die zelf via de "normale" manier de singleton gebruikt.

Het probleem is dat bij het twee maal laden van HandlerA (en dus de singleton) de Singletons van elkaar niet weten dat ze bestaan.

misschien moet ik ze in eenzelfde app domein laden oid ?

I haven't lost my mind! It's backed up on tape somewhere!

Pagina: 1