Laden...

Klasse ohne direkten Namen erstellen

Erstellt von Maggie123 vor 8 Jahren Letzter Beitrag vor 8 Jahren 2.035 Views
M
Maggie123 Themenstarter:in
4 Beiträge seit 2015
vor 8 Jahren
Klasse ohne direkten Namen erstellen

Hallo,
ich arbeite noch nicht lange mit C# und stehe vor folgendem Problem:

Während der Laufzeit sollen neue Klassen erstellt werden. Da ich nicht weiß wieviele es werden, kann ich diese aber nicht genau benennen.

Habe jetzt schon ziemlich lange im Internet gegoogelt, aber noch keine Lösung für das Problem gefunden.
Mein Denkansatz war, eine String Variable zu erzeugen, welche einen Namen für die Klasse erzeugt. Jedoch weiß ich jetzt nicht, wie ich die Klasse mithilfe der Variablen erstellen kann.
Bisheriger Programmcode :

string fg= "4";
string jn ="22";
// Werte von fg,jn wurden vorher zugewiesen, class "test" deklariert

string name = "Ezt" + fg + jn; // hier würde immer ein neuer Name erzeugt werden

test name = new test (fg,jn);
// hier der Fehler: das funktioniert leider nicht (wäre auch zu schön ;) )

Da ich gerade nichtmal weiß, ob das überhaupt funktioniert wäre ich wirklich froh, wenn mir jemand helfen könnte.

Mfg Maggie

Hinweis von Coffeebean vor 8 Jahren

Bitte benutze die richtigen Code-Tags [Hinweis] Wie poste ich richtig? Punkt 6

6.911 Beiträge seit 2009
vor 8 Jahren

Hallo Maggie123,

Da ich nicht weiß wieviele es werden, kann ich diese aber nicht genau benennen.

Vermutlich geht es in die Richtung von [FAQ] Variablennamen zur Laufzeit zusammensetzen / Dynamisches Erzeugen von Controls.

Während der Laufzeit sollen neue Klassen erstellt werden.

Das geht mittels [Artikel] Reflection und Metaprogrammierung

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

2.079 Beiträge seit 2012
vor 8 Jahren

Wenn Du noch nicht lange mit C# arbeitest, dann suche dir bloß einen anderen Weg aus 😉
Klassen zur Laufzeit erzeugen ist kein kleines Thema und spätestens bei den Methoden brauchst Du detailliertes Wissen, was der Compiler aus C# macht. Am Ende steht da nämlich CIL-Code und viele C#-Features, gibt es auf dieser Ebene nicht mehr und müssen händisch nach gebaut werden.
Du kannst es dir auch etwas einfacher machen und C#-Code generieren und dann kompilieren. Das geht zur Laufzeit, aber auch das wird schnell sehr umfangreich und es ist langsam.

In den meisten Fällen gibt es aber bessere Lösungen.
Wenn es z.B. darum geht, eine unbekannte Anzahl von Eigenschaften einem Objekt zuzuordnen, kannst Du z.B. folgendes machen:

public class MyClass
{
    private readonly IDictionary<string, object> _propertyValues;

    public IEnumerable<string> Properties
    {
        get { return _propertyValues.Keys; }
    }

    public MyClass(string[] propertieNames)
    {
        _propertyValues = propertieNames.ToDictionary(x => x, x => null);
    }

    public bool HasProperty(string propertyName)
    {
        return _propertyValues.ContainsKey(propertyName);
    }
    public object GetValue(string propertyName)
    {
        return _propertyValues[propertyName];
    }
    public void SetValue(string propertyName, object newValue)
    {
        _propertyValues[propertyName] = newValue;
    }
}

Bei der Nutzung, z.B. Darstellung der Daten in einem Fenster, musst Du dann natürlich über die entsprechenden Methoden auf die Werte zugreifen.
Das ist eine gängige Herangehensweise, wenn nicht bekannt ist, wie sich eine Klasse zur Laufzeit zusammen setzen wird.

3.170 Beiträge seit 2006
vor 8 Jahren

Hallo,

ich denke wie gfoidl, dass [FAQ] Variablennamen zur Laufzeit zusammensetzen / Dynamisches Erzeugen von Controls der Sache am nächsten kommt.

@Palladin007
Bei dynamisch zu erzeugenden Properties funzt das mit dem Dictionary natürlich, aber statt einer GetValue- und SetValue-Methode fände ich hier einen Indexer schöner.
Das Dictionary hat aber allgemien den Nachteil, dass man immer bei GetValue den Rückgabewert nochmal casten muss.

Wenn man bei der Erzeugung schon weiss, wie die Properties heissen sollen (aber nur dann), könnte man ggf. auch mit anonymen Typen arbeiten.

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

189 Beiträge seit 2014
vor 8 Jahren

Hallo Maggie123.

[...]ich arbeite noch nicht lange mit C#[...]

Ich hoffe du nimmst mir meine Gegenfrage nicht übel:
Meinst du wirklich Klassen oder meinst du Instanzen (einer Klasse) bzw. Objekte?

Vielleicht macht es auch Sinn, wenn du dein zugrunde liegendes Problem beschreibst, weshalb du meinst mehrere Klassen zur Laufzeit zu erstellen.
Es könnte auch eine Option sein mit Generics zu arbeiten (openbook: Visual C# Generische Datentypen).

VG Ezio

M
Maggie123 Themenstarter:in
4 Beiträge seit 2015
vor 8 Jahren

Hallo,

Vielen Dank für die Antworten!

Entschuldigt, da habe ich mich wohl falsch ausgedrückt, ich will neue Instanzen einer Klasse erstellen.

Kurze Beschreibung:

Ich bekomme ein Telegramm, welches aus unterschiedlich vielen Einzeltelegrammen besteht, diese haben wiederum noch mehr Untertelegramme. Ich versuche jetz die Telegramme in Einzeltelegramme aufzuspalten. Ich hab mir davor einen Code gebastelt, aus welchem ich lesen kann, wieviele Einzeltelegramme es gibt, und wie lang diese sind.
Nun war meine Idee, für jedes Einzeltelegramm eine Instanz einer Klasse "Einzeltelegramm" anzulegen. Dort würde ich die verschiedenen Eigenschaften speichern und eventl Methoden zum weiteraufspalten.

Ich habe also schon eine Klasse "Einzeltelegramm" erstellt, habe ihr auch schon Eigenschaften zugewiesen usw.
So... ich will also zur Laufzeit neue Instanzen der Klasse "Einzeltelegramm" erstellen. Aber ich kann diese ja schlecht per Hand benennen.
Ich kann zwar eine String Variable "Name" erstellen, und diese dann so füllen, dass es keine doppelten Namen gibt.
Jedoch funktioniert
einzeltelegram name = new einzeltelegramm (daten);
nicht.

Problem:

Und genau hier liegt mein Problem. Also ich habe alle Daten, die ich für die Klasse brauche, Klasse ist auch schon erstellt, aber ich weiß nicht wie ich hier neue Instanzen erstellen soll, ohne dass ich ihr direkt einen Namen geben kann.

Ich hoffe, ich hab diesmal nicht wieder formulierungsfehler in der Fragestellung.

2.298 Beiträge seit 2010
vor 8 Jahren

Hallo Maggie123,

ich denke du hast hier ein klares Verständnisproblem. In welcher Form erhältst du das Telegram?

Die Zuweisung von Daten über den Konstruktor einer Klasse geht nur dann, wenn es auch einen Konstruktor gibt, der diese Daten entgegen nimmt.

Ansonsten sofern ich dich richtig verstehe:


Telegrammliste erstellen

Für jeden Telegramdatensatz in Ergebnis
      Neues Telegraminstanz erstellen
      Telegraminstanz mit Werten belegen
      Telegraminstanz zu Telegramliste hinzufügen

Weitere Behandlung der Telegramme

Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |

3.170 Beiträge seit 2006
vor 8 Jahren

Hallo,

wenn Du die Einzeltelegramme mit einem Namen ansprechen willst, den Du zur Laufzeit zusammensetzt, hilft Dir hier am besten ein Dictionary<string, Einzeltelegramm>.
Da kannst Du dann die einzelnen Instanzen unter ihrem Namen ablegen.

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

W
955 Beiträge seit 2010
vor 8 Jahren

@Palladin007
Hi,
wieso implementiertst du in deinem Beispiel nicht einfach den Indexer der Klasse?


         public object this[String propertyName]
         {
            get {
                return _propertyValues[propertyName]; 
            }
            set {
                _propertyValues[propertyName] = newValue;
            }
         }

UPPS, hat MarsStein schon angemeckert...

1.029 Beiträge seit 2010
vor 8 Jahren

Hi,

für mich hört sich das klar nach einer Baumstruktur an, in der eine Instanz schlicht weitere Instanzen erzeugt.

public class Telegram
	{
		// übergeordnetes Telegramm (sofern vorhanden)
		public Telegram Parent { get; protected set; }

		// untergeordnete Telegramme - sofern vorhanden
		public List<Telegram> Children { get; set; }

		// Die Eigenschaften des (Einzel)Telegramms
		//...

		public Telegram(string inputToParse, Telegram parent = null)
		{
			Parent = parent;
			Children = new List<Telegram>();
			ParseInput(inputToParse);
		}

		protected virtual void ParseInput(string input)
		{
			// input einlesen - und ggf. weitere Telegramme erstellen
			foreach (string part in input.Split(new char[] {' '})) // nur ein Beispiel
			{
				Telegram child = new Telegram(part, this);
				Children.Add(child);
			}
		}

Edit: Wenn du die dann später in irgend einer Form ausgeben / weiter mit arbeiten möchtest hast die quasi ein Haupttelegramm - und kannst von dort aus schlicht immer tiefer die untergeordneten Telegramme ansprechen.

LG

T
67 Beiträge seit 2010
vor 8 Jahren

Wie genau willst Du die Einzeltelegramme später weiter verarbeiten? Einfach der Reihe nach oder gezielter Zugriff auf einzelne Telegramme?

Wenn Du die eingehenden Telegramme später nur der Reihe nach abarbeiten willst brauchst Du dir keine Gedanken um Variablennamen zur Laufzeit und ähnliches machen.

Ein kleiner Denkansatz wie Du das z.B. lösen könntest

 List<einzeltelegramm> lstET = new List<einzeltelegramm>();
einzeltelegramm ET = null;

for (int i = 0; i < 1000; i++)
{   //Beispiel 1000 Instanzen
    ET = new einzeltelegramm(daten);
    lstET.Add(ET);
}

M
Maggie123 Themenstarter:in
4 Beiträge seit 2015
vor 8 Jahren

Super, das geht definitiv in die richtige Richtung 😉

@ inflames2k: Ich hatte die Listen noch nicht im Kopf, aber so ähnlich hatte ich es im Kopf 😉

@Talon: ich will auf die Einzeltelegramme auch noch später zugreifen können, also nicht nur der Reihe nach.

@ Rest:
super, das mit dem Dictionary scheint ziemlich perfekt für dieses Problem zu sein.

Ich habe aber noch eine allgemeine Frage:
Ich müsste meine Instanz der Klasse Einzeltelegramm ja trotzdem benennen. Bspw. "NeuesET". Jetzt die Frage: wäre das OK, für neue Instanzen den selben Namen zu nehmen, wenn ich diese mit!"= new Einzeltelegramm(daten); " erstelle?

Demnach müssten die Werte in der Dictionary immer "NeuesET" heißen, aber mit unterschiedlichen Werten befüllt sein.

Code in der Schleife:

einzeltel NeuesET= new einzeltel(l, fg, id, jn, anzde, daten);

                nameeinzeltelegram.Add((i + 1), NeuesET);
2.298 Beiträge seit 2010
vor 8 Jahren

Hallo,

der Variablenname ist Schall und Rauch. Nachdem du das Objekt zum Dictionary hinzugefügt hast steht da nicht drin "Objekt NeuesET" sondern "Objekt vom Typ Einzeltelegram".

Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |

M
Maggie123 Themenstarter:in
4 Beiträge seit 2015
vor 8 Jahren

super, vielen Danke, ihr habt mir echt geholfen!