[C#] Tijdens runtime weten wie erft van een class

Pagina: 1
Acties:
  • 324 views sinds 30-01-2008
  • Reageer

  • robertpNL
  • Registratie: Augustus 2003
  • Niet online
Hey,

Tijdens runtime wil ik weten wie erft van een base class (of van een abstracte class).

Voorbeeld:

code:
1
2
3
4
5
public class A
{}
public class B : A
{}
public class C : A


Classes B en C erven van A.

Maar hoe kom ik tijdens runtime achter dat B en C (en misschien D, E, etc) gebruik maken van class A. M.a.w, wie heeft class A als base class (voor dit voorbeeld is het antwoord dus B en C).

Nu heb ik zelf even zitten zoeken, maar ik kwam op twee manieren die geen antwoord gaven voor mijn probleem:
- System.Type.GetType("namespace.A")
en dan vind ik geen method/property die mij hier een antwoord op kan geven
- System.Reflection. ...
Tja, niet echt een class gevonden binnen de System.Reflection die mij hierin kan helpen.

Of...kan het gewoon niet.

De reden voor deze vraag is dat ik zonder extra code een class kan toevoegen, die erft van een base class, en tijdens runtime wordt ingelezen en wordt gebruikt (ik hoop dat je het snapt).

  • matthijsln
  • Registratie: Augustus 2002
  • Laatst online: 14-04 13:30
Misschien kan je je probleem beter op een andere manier oplossen? Probeer je een plug-in systeem of iets dergelijks te maken?

  • r5d
  • Registratie: Februari 2002
  • Niet online

r5d

Read more, write less...

Dit kan met behulp reflectie, maar ik weet niet exact de methode meer (volgens mij BaseType.FullName). Probeer onderstaande code eens (niet getest).

code:
1
2
3
4
5
6
7
assembly = Assembly.LoadFrom("C:\hierjeassembly.dll");

foreach (Type metadata in assembly.GetTypes()) {
  if (metadata.IsClass) {
    Console.WriteLine(metadata.BaseType.FullName);
  }
}

Later betaal je meer, maar dan heb je wel een gratis datalimiet....


  • Twilight Burn
  • Registratie: Juni 2000
  • Laatst online: 16-02 23:04
Iig, als je "A" compile-time weet, kun je d.m.v. reflection (en dan alle klassen in een assembly doorlopen) met "if (eenKlasse is A)" wel kijken of hij van A erft. Volgens mij kun je A ook runtime invullen met GetType(varMetTypeA), maar dat weet ik niet zeker.

  • remyblok
  • Registratie: Oktober 2003
  • Laatst online: 26-03 10:20
Kijk is in de MSDN naar de class System.Type. Hierin zitten allerei functies om interfaces en supperclasses te vinden.
Maar de rede dat je dit nodig hebt is me verre van helder.

  • robertpNL
  • Registratie: Augustus 2003
  • Niet online
PimpDiddy en Twilight Burn: bedankt. Hier kan ik zeker ook wat mee.
remyblok schreef op maandag 30 januari 2006 @ 22:54:
Kijk is in de MSDN naar de class System.Type. Hierin zitten allerei functies om interfaces en supperclasses te vinden.
Maar de rede dat je dit nodig hebt is me verre van helder.
Het System.Type class heb ik zeker bekeken maar ik toch kan ik in deze class niet mijn antwoord vinden.

Verder is je verre van helderheid begrijpelijk want ik leg ook niet uit waarom ik zoiets wil. Maar het komt erop neer dat ik 1) het interresant vind ik wat meer met reflection class te weten te komen (dus een leuk leermoment), en 2) ik een situatie heb waar ik zeker weet efficienter te kunnen programmeren.

Het achtergrond verhaal wil ik je zeker een keer kwijt, maar ik ben nog zo aan het experimenteren dat het verhaal zeker onbegrijpelijk en te lang zal worden. :)

  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 13-04 14:28
Waarschijnlijk ben je al geholpen met de is. Dus als je een object binnenkrijgt in een functie kan je controleren of ie van A afgeleid is door te checken op if (object is A) {...}.

edit:

De is-operator bedoel ik dan natuurlijk. Overzicht van de operators in C#.

[ Voor 44% gewijzigd door riezebosch op 31-01-2006 00:02 ]

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


  • whoami
  • Registratie: December 2000
  • Laatst online: 20:38
riezebosch schreef op maandag 30 januari 2006 @ 23:50:
Waarschijnlijk ben je al geholpen met de is. Dus als je een object binnenkrijgt in een functie kan je controleren of ie van A afgeleid is door te checken op if (object is A) {...}.

edit:

De is-operator bedoel ik dan natuurlijk. Overzicht van de operators in C#.
Dat kan je idd doen, maar, dan moet je al 'vermoeden' hebben waar die class van overerft.
Als je een hele class - hierarchy hebt, en je wilt weten van welke class , class A overerft, dan is het denk ik beter om met reflection te doen ipv een hele if / switch boom te maken.

Echter, ik vraag me ook af waarom je dit wilt weten ?

https://fgheysels.github.io/


  • robertpNL
  • Registratie: Augustus 2003
  • Niet online
whoami schreef op dinsdag 31 januari 2006 @ 08:50:
[...]

Echter, ik vraag me ook af waarom je dit wilt weten ?
Oké, ik zal proberen dit zo helder mogelijk over te laten komen.

Er is één base class. Verschillende classes erven hiervan. Zo'n class (die erft) bevat gebruikersinstellingen die uiteenlopen van boolean tot een collection. Iedere property heeft een Attribute. Daarin wordt verteld waar in de registry de betreffende property moet worden opgeslagen of worden opgehaald.

Dan is er een andere class met een collection die alle classes bewaard met gebruikersinstellingen. Dus m.a.w. de collection bevat classes die erven van de base class. Maar in code moet ik iedere class met gebruikersinstellingen aan de collection toevoegen. En dat vind ik wat onzin, niet-efficient programmeren.

Wat ik dus zocht is een soort herkenning tijdens runtime welke classes erven van een base clas en dus tijdens runtime automatisch aan een collection wordt toegevoegd.

In het kort de praktijk:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
public class BaseUserSettings
{
   protected bool SaveSettingsInReg() { ...}
   protected bool ReadSettingsFromReg() { ...} 
}
public class UserSettingsA : BaseUserSettings
{
  // allerlei propertys van instellingen in categorie A met een attribute
}
public class UserSettingsB : BaseUserSettings
{
  // allerlei propertys van instellingen in categorie A met een attribute
}


Nou hierboven zie je een base class met twee categorien aan gebruikersinstellingen (categorie A en Bee). Deze bevatten dus propertys met iedere property een class ge-erft van System.Attribute maar doet verder even niet ter zake.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class UserSettings
{
   private ArrayList pUserSettings = new ArrayList();
   public UserSettings
   {
       pUserSettings.Add(new UserSettingsA());
       pUserSettings.Add(new UserSettingsB());
   }

   public void SaveSettings()
   { 
      foreach ... in pUserSettings { ...Save() }
   }
}


(ik tik de code even uit mijn hoofd in, dus let even niet op de kleine foutjes).

En dan gaat het dus om de constructor van deze class. Die zou efficienter moeten kunnen. Dus dat ik voor iedere class die ik aanmaken voor het houden van gebruikersinstellingen niet een regeltje hoeft toe te voegen voor het toevoegen van de class aan de collection.

M.a.w. als ik een nieuwe gebruikersinstellingen class aanmaak, dat deze door class UserSettings wordt "herkend".

Oke oke, misschien ga ik erg ver en dat er makkelijker manieren om hier mee om te gaan geloof ik zeker, maar het is ook een leermoment voor mijzelf :)

Ik hoop dat jullie me begrijpen.

  • whoami
  • Registratie: December 2000
  • Laatst online: 20:38
Is het niet eenvoudiger en beter als je gebruikt maakt van polymorphisme ?

Je base-class mag in principe niets weten van de classes die afgeleid zijn van die base-class.
Het is dus beter dat je in je base class in de save en load methods de specifieke data van die base-class gaat ophalen / saven, en in de afgeleide classes, de specifieke data van die afgeleide class ophaalt / saved (incl de settings van de base class).
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class BaseSetting
{
       int a;

      public virtual void Save()
       {
           // schrijf a weg
       }
}

public class Other : BaseSetting
{
      int x;

      public override Save
      {
             base.Save();
              // schrijf hier ook nog x weg.
      }
}


En dan kan je ook nog een SettingsManager maken die de settings kan wegschrijven of ophalen.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class SettingsManager
{
      private ArrayList  settings = new ArrayList();

      public void AddSetting( BaseSetting bliep )
      {
            settings.Add (bliep);
      }

      public void SaveSettings()
      {
            foreach( BaseSetting bliep )
            {
                 bliep.Save();
            }
      }
}

[ Voor 25% gewijzigd door whoami op 31-01-2006 10:05 ]

https://fgheysels.github.io/


Verwijderd

misschien dat je gebruik kan maken van het 'Base' keyword. Dat betekent 'this' maar heeft dan betrekking op de baseclass waarvan geerft wordt.

Ik ben net vorige week op cursus c# geweest dus ik heb weinig praktijk ervaring, maar zit wel vol met theoretische kennis :P

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 18:16

curry684

left part of the evil twins

robertpNL schreef op dinsdag 31 januari 2006 @ 09:47:
[...]

En dan gaat het dus om de constructor van deze class. Die zou efficienter moeten kunnen. Dus dat ik voor iedere class die ik aanmaken voor het houden van gebruikersinstellingen niet een regeltje hoeft toe te voegen voor het toevoegen van de class aan de collection.
Such is life, je kunt niet alles automatiseren. In dit geval ben je gewoon foute aannames aan het doen, omdat je code al de mist in zou gaan als ik abstract class AdvancedUserSettings van BaseUserSettings zou deriven en daar vervolgens weer AdvancedA en AdvancedB zou inheriten. Je probeert unrelated data automatisch te achterhalen, en da's per definitie huilen.

Dat daargelaten lijkt je class-model me sowieso onzinnig in dit geval, ik zie geen enkele reden om 300 verschillende derivants van BaseUserSettings te maken die je vervolgens in UserSettings wil gaan aggregeren. Het probleem is dus afaics dat je een ranzige oplossing probeert te implementeren voor een correct probleem dat enkel ontstaan is door foute designkeuzes. Dus, vertel eens, wat probeer je nu eigenlijk te bereiken? Functioneel dus, en niet technisch :)

Professionele website nodig?


  • robertpNL
  • Registratie: Augustus 2003
  • Niet online
curry684 schreef op dinsdag 31 januari 2006 @ 10:42:
[...]

Such is life, je kunt niet alles automatiseren. In dit geval ben je gewoon foute aannames aan het doen, omdat je code al de mist in zou gaan als ik abstract class AdvancedUserSettings van BaseUserSettings zou deriven en daar vervolgens weer AdvancedA en AdvancedB zou inheriten. Je probeert unrelated data automatisch te achterhalen, en da's per definitie huilen.

Dat daargelaten lijkt je class-model me sowieso onzinnig in dit geval, ik zie geen enkele reden om 300 verschillende derivants van BaseUserSettings te maken die je vervolgens in UserSettings wil gaan aggregeren. Het probleem is dus afaics dat je een ranzige oplossing probeert te implementeren voor een correct probleem dat enkel ontstaan is door foute designkeuzes. Dus, vertel eens, wat probeer je nu eigenlijk te bereiken? Functioneel dus, en niet technisch :)
:) Ja was ik al bang voor.

Functioneel: een manier waarmee ik niet voor iedere userinstelling een partij codes moet maken en dat ik op een simpele manier een userinstelling kan toevoegen en kan gebruiken binnen de applicatie.

  • whoami
  • Registratie: December 2000
  • Laatst online: 20:38
Zie mijn voorbeeld. :)

https://fgheysels.github.io/


  • robertpNL
  • Registratie: Augustus 2003
  • Niet online
:) Jongens, bedankt.
Pagina: 1