[C#] Naam van object nodig, maar reflection lukt niet.

Pagina: 1
Acties:

  • ThaLaw
  • Registratie: Maart 2001
  • Laatst online: 25-11 09:41
Eerst even een stukje code: (simplified)

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
public class MyClass
{
   public Hashtable table1 = new Hashtable();
   public Hashtable table2 = new Hashtable();
   public Hashtable proplist = new Hashtable();

   public MyClass()
   {
    ... // Some inits, tables are filled
    proplist.Add(1039,table1);
    proplist.Add(1025,table2);
   }
}


Het gaat my nu om de hashtable proplist.
Het object dat ik terugkrijg, wanneer ik bijvoorbeeld proplist[1025] opvraag, is ook weer een Hashtable (table2), maar ik zoek nu een manier om de naam van dat object terug te krijgen als String. In dit geval ben ik dus op zoek naar "table2".

Ik heb System.Reflection bekeken, maar dit krijg ik niet aan de praat, ik krijg steeds alleen maar de typenaam hashtable terug. Is er een manier om dit voor elkaar te krijgen?

  • Koppensneller
  • Registratie: April 2002
  • Laatst online: 16:01

Koppensneller

winterrrrrr

Omdat het de naam is van de referentie naar het object, ipv het object zelf, gaat dit niet lukken. Stel dat je 2 referenties, table2 en table3, naar dezelfde hashtable zou hebben, welke naam zou je dan terug moeten/willen krijgen?

  • ThaLaw
  • Registratie: Maart 2001
  • Laatst online: 25-11 09:41
KoppenSneller schreef op maandag 04 juni 2007 @ 13:29:
Omdat het de naam is van de referentie naar het object, ipv het object zelf, gaat dit niet lukken. Stel dat je 2 referenties, table2 en table3, naar dezelfde hashtable zou hebben, welke naam zou je dan terug moeten/willen krijgen?
Maar table1 en table2 zijn toch de unieke objecten?
Ik sla een referentie naar table1 op in de proplist tabel... maar als ik het object uit die proplist opvraag, krijg ik weer een nieuwe referentie naar dat object...

...terwijl ik dit typ, snap ik wat jij bedoelt... :P

Ik ben dus eigenlijk op zoek naar 1 van de referentienamen.. en dat is wrs. iets dat niet mogelijk is.

  • cspare
  • Registratie: Oktober 2006
  • Laatst online: 29-07 22:19

cspare

What the deuce?!

De namen van variabelen gaan inderdaad verloren bij het compilatie process.

[ Voor 4% gewijzigd door cspare op 05-06-2007 08:50 ]

The one who says it cannot be done, should never interrupt the one who is doing it.


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

MTWZZ

One life, live it!

Je wil dus feitelijk "table1" of "table2" als resultaat hebben?
Als dat je doel is dan gaat dat helaas niet lukken. Die variabele namen worden namelijk door de compiler veranderd.

Nu met Land Rover Series 3 en Defender 90


  • Koppensneller
  • Registratie: April 2002
  • Laatst online: 16:01

Koppensneller

winterrrrrr

Wat je wel kunt doen, is de Tag property hiervoor gebruiken...

  • whoami
  • Registratie: December 2000
  • Laatst online: 00:54
Zowiezo gaat dit niet lukken, aangezien die namen daar gewoon zijn voor de programmeur. Het is een hulpmiddel dat je programmeertaal je biedt aan de programmeur. Die variable stelt eigenlijk niets meer en niets minder voor dan een geheugen-adres.

https://fgheysels.github.io/


  • DrDelete
  • Registratie: Oktober 2000
  • Laatst online: 20:46
Je zou een eigen Hashtable kunnen maken door over te erven van Hashtable. Voeg een string-property Name toe en maak een constructor initializer aan die de name als parameter meekrijgt, maak de default constructor private.

  • ThaLaw
  • Registratie: Maart 2001
  • Laatst online: 25-11 09:41
Ik heb het als volgt opgelost, is voor mijn situatie voldoende:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class MyClass
{
   public NamedHashtable table1 = new NamedHashtable("table1");
   public NamedHashtable table2 = new NamedHashtable("table2");
   public NamedHashtable proplist = new NamedHashtable("proplist");

   public MyClass()
   {
    ... // Some inits, tables are filled
    proplist.Add(1039,table1);
    proplist.Add(1025,table2);
   }
}

public sealed class NamedHashtable : Hashtable
{
        private string c_name = "";
        public String Name
        {
            get
            {
                return c_name;
            }
        }

        public NamedHashtable(string TableName)
        {
            c_name = TableName;
        }
}


Ik kan de naam nu bereiken via

code:
1
((NamedHashtable)proplist[1025]).Name;


/edit:
@DrDelete: Je had hetzelfde idee zie ik :P

  • DrDelete
  • Registratie: Oktober 2000
  • Laatst online: 20:46
ThaLaw schreef op maandag 04 juni 2007 @ 13:48:
Ik heb het als volgt opgelost, is voor mijn situatie voldoende:

@DrDelete: Je had hetzelfde idee zie ik :P
Bijna, uit oogpunt van onderhoud: private constructor maken

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 23:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

Waarom zou je dit in hemelsnaam willen?

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • HawVer
  • Registratie: Februari 2002
  • Laatst online: 29-11 23:30
Wat .oisyn vraagt vind ik eigenlijk best een interessante vraag. Wat heeft een naam van een variabele te maken met de data zelf? Volgens mij maak je dan echt een denkfout.

http://hawvie.deviantart.com/


  • Xiphalon
  • Registratie: Juni 2001
  • Laatst online: 16:44
Je kan van het object de GetType() methode aanroepen, en in het System.Type object wat je dan terugkrijgt, zit een Name property. Deze geeft de naam van het type terug.

De naam van de variable zelf is met compileren kwijt geraakt, en ik kan me geen reden verzinnen
waarom je die zou willen hebben.

Sowieso is het in de TS uiteraard gewoon Proplist :+

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
darkmage schreef op maandag 04 juni 2007 @ 17:39:
De naam van de variable zelf is met compileren kwijt geraakt, en ik kan me geen reden verzinnen
waarom je die zou willen hebben.
De naam van de variabele is ws gewoon mee gecompileerd, en niet kwijt geraakt. Maar om van een object de variabele naam te achterhalen is idd wel onmogenlijk. Er kunnen namenlijk x aantal variabelen naar je object wijzen dus er valt niet te zeggen "Dit is de variabele naam van deze instance".

Verder zou ik idd ook niet weten waarom je het zou willen. Als je een string wilt weten is dat een eigenschap van een object en zul je dat in het object op moeten nemen.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • ThaLaw
  • Registratie: Maart 2001
  • Laatst online: 25-11 09:41
Ik heb inderdaad de naam van de variabele nodig, en niet van het type.

Het type is namenlijk in alle gevallen Hashtable.

Het gaat hier om een static fixed class, die vol zit met tabellen. Die tabellen hebben een naam die staat voor wat er in die tabellen zit, maar ik dacht dus de naam van de variabele terug te kunnen krijgen en dan wist ik genoeg, helaas, die var-namen zijn weg na compilen (wat logisch is als ik even wat verder had doorgedacht, er kunnen meerdere refs zijn)

Vandaar het toevoegen van het tagje ;-)

Hier een stukje code uit me werkelijke app, misschien dat dan duidelijk is waarom ik dit nodig had:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
    public  class NamedHashtable : Hashtable
    {
        private string c_name = "";
        public String Name
        {
            get
            {
                return c_name;
            }
        }

        public NamedHashtable(string TableName)
            : base()
        {
            c_name = TableName;
        }
    }

    public static class CameraSettings
    {

        public static NamedHashtable MeteringMode = new NamedHashtable("MeteringMode");
        public static NamedHashtable ExposureComp = new NamedHashtable("ExposureComp");

        //... en zo nog 25 tabellen...

        public static Hashtable PropList = new Hashtable();

        static CameraSettings()
        {
            tableInit();
        }

        private static void tableInit()
        {
            MeteringMode.Add((int)1, "Spot Metering");
            MeteringMode.Add((int)3, "Evaluative Metering");
            MeteringMode.Add((int)4, "Partial Metering");
            MeteringMode.Add((int)5, "Center-Weighted Average Metering");
            MeteringMode.Add(0xFFFFFFFF, "unkown");

            ExposureComp.Add((int)0x18, "+3");
            ExposureComp.Add((int)0x15, "+2 2/3");
            ExposureComp.Add((int)0x14, "+2 1/2");
            ExposureComp.Add((int)0x13, "+2 1/3");
            ExposureComp.Add((int)0x10, "+2");
            ExposureComp.Add((int)0xD, "+1 2/3");
            ExposureComp.Add((int)0xC, "+1 1/2");
            ExposureComp.Add((int)0xB, "+1 1/3");
            ExposureComp.Add((int)0x8, "+1");
            ExposureComp.Add((int)0x5, "+2/3");
            ExposureComp.Add((int)0x4, "+1/2");
            ExposureComp.Add((int)0x3, "+1/3");
            ExposureComp.Add((int)0x0, "0");
            ExposureComp.Add((int)0xFD, "-1/3");
            ExposureComp.Add((int)0xFC, "-1/2");
            ExposureComp.Add((int)0xFB, "-2/3");
            ExposureComp.Add((int)0xF8, "-1");
            ExposureComp.Add((int)0xF5, "-1 1/3");
            ExposureComp.Add((int)0xF4, "-1 1/2");
            ExposureComp.Add((int)0xF3, "-1 2/3");
            ExposureComp.Add((int)0xF0, "-2");
            ExposureComp.Add((int)0xED, "-2 1/3");
            ExposureComp.Add((int)0xEC, "-2 1/2");
            ExposureComp.Add((int)0xEB, "-2 2/3");
            ExposureComp.Add((int)0xE8, "-3");
            ExposureComp.Add(0xFFFFFFFF, "unkown");


            // ... en zo nog 25 tabellen...

            PropList.Add((int)EDSDK.PropID_MeteringMode, MeteringMode);
            PropList.Add((int)EDSDK.PropID_ExposureCompensation, ExposureComp);   
       }
    }


Ergens anders in een eventhandler, waar ik alelen beschik over een integer die het type property aanwijst...

code:
1
2
3
...
String changedPropertyName =((NamedHashtable)CameraSettings.PropList[(int)InPropertyID]).Name;
...


Mocht iemand nu nog steeds zeggen, dat had ik effe wat handiger aangepakt, dan hoor ik dat graag, er valt nog een hoop te leren ! :+

P.S. @MrDelete: private constructor werkte niet, want dan is deze onbereikbaar.

  • Free rider
  • Registratie: November 2006
  • Laatst online: 27-11 02:21
Als je met debug-informatie compileert, en enige ervaring met de binnenkant van debuggers hebt, kijk dan eens naar de Debug Interface Access SDK, zie http://msdn2.microsoft.co...rary/x93ctkx8(VS.80).aspx

Zoals eerder gesteld kan je niet van een gegeven object alle variabelen vinden die een referentie naar het object hebben. Maar je kan wel alle variabelen aflopen en vaststellen of zij naar het betreffende object wijzen. Ga maar eens debuggen in Visual Studio, stop op een break point en kijk bij Debug - Windows - Locals.

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Free rider schreef op woensdag 06 juni 2007 @ 10:19:
Als je met debug-informatie compileert, en enige ervaring met de binnenkant van debuggers hebt, kijk dan eens naar de Debug Interface Access SDK, zie http://msdn2.microsoft.co...rary/x93ctkx8(VS.80).aspx

Zoals eerder gesteld kan je niet van een gegeven object alle variabelen vinden die een referentie naar het object hebben. Maar je kan wel alle variabelen aflopen en vaststellen of zij naar het betreffende object wijzen. Ga maar eens debuggen in Visual Studio, stop op een break point en kijk bij Debug - Windows - Locals.
Wat natuurlijk niet echt een mooie oplossing is :X

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • voodooless
  • Registratie: Januari 2002
  • Laatst online: 30-11 11:20

voodooless

Sound is no voodoo!

Tjonge, zou je dat soort tabellen wel hardcoden? Een filetje met die info lijkt me veel makkelijker bij te houden.

Do diamonds shine on the dark side of the moon :?


  • DrDelete
  • Registratie: Oktober 2000
  • Laatst online: 20:46
ThaLaw schreef op dinsdag 05 juni 2007 @ 13:20:

P.S. @MrDelete: private constructor werkte niet, want dan is deze onbereikbaar.
Dit lukt bij mij wel hoor ;)

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class MyHashtable : Hashtable
    {
        private string name;

        private MyHashtable()
        {
            
        }

        public MyHashtable(string name)
        {
            this.name = name;
        }


        public string Name
        {
            get
            {
                return name;
            }
        }
    }


Een constructor initializer zal, als je niks bijzonders aangeeft, altijd eerst de base z'n default constructor aanroepen.

In dit geval zal "public MyHashtable(string name)" eerst de hashtable's default constructor aanroepen alvorens het in zijn eigen constructor initializer komt.

De base toevoeging achter een constructor initializer is alleen nodig indien je een specifieke constructor initializer van de base class wilt aanroepen.

[ Voor 31% gewijzigd door DrDelete op 06-06-2007 12:04 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 23:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

Waarom zou je de default constructor private willen maken ipv 'm gewoon niet te definieren?

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • DrDelete
  • Registratie: Oktober 2000
  • Laatst online: 20:46
.oisyn schreef op woensdag 06 juni 2007 @ 12:02:
Waarom zou je de default constructor private willen maken ipv 'm gewoon niet te definieren?
Je moet de default constructor private maken als je zeker wilt zijn dat alleen een constructor initializer gebruikt mag worden en niet de default. In dit scenario zou ik hier voor kiezen.

Daarnaast zou ik altijd een default constructor coderen, afhankelijk van het scenario kies je de juiste access modifier voor de default constructor. Bij het weglaten van de default constructor en het toevoegen van een constructor initializer kun je later in grote problemen komen, dit gebeurt namelijk als een ontwikkelaar in eens besluit om toch deze class een private constructor te geven, terwijl andere classes misschien toch stiekem de default constructor van deze class hadden gebruikt.

Zie Framework Design Guidelines.

[ Voor 56% gewijzigd door DrDelete op 06-06-2007 12:29 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 23:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

Uhm, als je een andere constructor dan de default constructor definieert, dan wordt de default constructor ook niet meer gegenereerd en kan hij dus sowieso niet gebruikt worden. Het extra definieren van een private default constructor is dus nogal nutteloos.

Bovendien staat wat jij beweert ook helemaal niet op die pagina die jij aanhaalt [deze dus, is nu weggeedit] (er staat dat je een private default constructor moet maken als je class alleen static members bevat of niet bedoelt is om te instantieren)
DrDelete schreef op woensdag 06 juni 2007 @ 12:06:
Bij het weglaten van de default constructor en het toevoegen van een constructor initializer kun je later in grote problemen komen, dit gebeurt namelijk als een ontwikkelaar in eens besluit om toch deze class een private constructor te geven, terwijl andere classes misschien toch stiekem de default constructor van deze class hadden gebruikt.
Dat slaat nergens op. Andere classes kunnen helemaal niet stiekem de default ctor van je class gebruiken aangezien die niet gedefinieerd was en er een non-default ctor was gedefinieerd, waardoor de default ctor helemaal niet bestaat. De situatie die jij schetst is voor classes met helemaal geen ctors (en dus een impliciet gegenereerde default ctor), waardoor andere classes afhankelijk zijn van deze default ctor. Als je dan ineens een non-default ctor toe gaat voegen, dan verdwijnt de default ctor en breekt de huidige code dus. Als een class echter een nondefault ctor heeft en geen default ctor hoeft te hebben, dan is er geen enkele reden om dan maar een private default ctor te definieren (tenzij de class een default instantie van zichzelf wilt kunnen maken), aangezien hij sowieso nooit aangeroepen kan worden door anderen. En dat staat dus ook niet in die guideline die je aanhaalt.

[ Voor 71% gewijzigd door .oisyn op 06-06-2007 12:36 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • DrDelete
  • Registratie: Oktober 2000
  • Laatst online: 20:46
.oisyn schreef op woensdag 06 juni 2007 @ 12:17:
Uhm, als je een andere constructor dan de default constructor definieert, dan wordt de default constructor ook niet meer gegenereerd en kan hij dus sowieso niet gebruikt worden. Het extra definieren van een private default constructor is dus nogal nutteloos.

Bovendien staat wat jij beweert ook helemaal niet op die pagina die jij aanhaalt [deze dus, is nu weggeedit] (er staat dat je een private default constructor moet maken als je class alleen static members bevat of niet bedoelt is om te instantieren)


[...]

Dat slaat nergens op. Andere classes kunnen helemaal niet stiekem de default ctor van je class gebruiken aangezien die niet gedefinieerd was en er een non-default ctor was gedefinieerd, waardoor de default ctor helemaal niet bestaat. De situatie die jij schetst is voor classes met helemaal geen ctors (en dus een impliciet gegenereerde default ctor), waardoor andere classes afhankelijk zijn van deze default ctor. Als je dan ineens een non-default ctor toe gaat voegen, dan verdwijnt de default ctor en breekt de huidige code dus. Als een class echter een nondefault ctor heeft en geen default ctor hoeft te hebben, dan is er geen enkele reden om dan maar een private default ctor te definieren (tenzij de class een default instantie van zichzelf wilt kunnen maken), aangezien hij sowieso nooit aangeroepen kan worden door anderen. En dat staat dus ook niet in die guideline die je aanhaalt.
Je hebt gelijk, ik bedoelde dit:

Bekijk het vanuit een evolutionair oogpunt: stel dat je een class maakt zonder enige constructors, dan heb je in feite altijd de default constructor bij de hand. Als je een framework API zou maken dan zullen andere classes altijd jouw default constructor gebruiken. Het wordt dan gevaarlijk als je ineens een constructor initializer zou toevoegen. Alle andere classes breken dan inderdaad. In dit scenario wordt de constructor initializer bij eerste oplevering van de code al opgeleverd en het is waarschijnlijk geen framework API, dan levert dit geen direct gevaar op.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 23:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

In dit scenario wordt de constructor initializer bij eerste oplevering van de code al opgeleverd en het is waarschijnlijk geen framework API, dan levert dit geen direct gevaar op.
Hence my point, de extra private default ctor is in dit geval een beetje nutteloos om expliciet toe te voegen, je wint er helemaal niets mee :).

Overigens vind ik die guideline voor een expliciete default ctor als de gegenereerde default ctor ook voldoet enigszins debatable. Je zou natuurlijk kunnen stellen dat voor iedere class zonder expliciete ctors waar je een extra ctor aan toe gaat voegen, je ook de default ctor nog even moet specificeren. Maar goed, dat is natuurlijk gewoon iets dat je aan moet leren en anders vergeten kan worden, dus dat opnemen in een guideline kan op zich handig zijn.

Let er trouwens wel op dat in een taal als C++ een class zonder ctors een aggregate is, en je naast de default ctor dus ook initializer lists kunt gebruiken om een instantie te initializeren:
C++:
1
2
3
4
5
6
7
8
struct A { int i, j; };
struct B { int i, j; B(); };

int main()
{
    A a = { 1, 2 }; // ok, A is een aggregate
    B b = { 3, 4 }; // niet ok, B heeft een ctor
}


Door te specificeren dat een default ctor altijd gedefinieerd moet worden, kun je je objecten dus ook nooit initializeren met initializer-lists, en zal code ook nooit breken waarneer je besluit een andere ctor toe te voegen.

Overigens krijgt C++09 de 'sequence constructor' feature, waarbij je initializer-lists kunt gebruiken om je object te constructen.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.

Pagina: 1