Laden...

Zugriff auf Unterzweig von verschachtelter abstrakter Klasse

Letzter Beitrag vor 5 Jahren 18 Posts 3.246 Views
Zugriff auf Unterzweig von verschachtelter abstrakter Klasse

Hallo Leute

Ich habe ein Problem, mit einer selbstgeschriebenen abstrakten Klasse.
Bei Microsoft gibt es ja die App1.settings Dateien. In denen kann man eigene Eigenschaften definieren auf die man wiederum in C# über Assemblyname.App1.Default.MeineEinstellung1 zugreifen kann. Daher es gibt Methoden die in Assemblyname.App1 untergebracht sind und weitere eigene Eigenschaften, die in App1.Default.MeineEinstellung1 untergebracht sind. Mir geht es hier um die Strukturierung der Klasse.

Selber habe ich vor eine abstrakte Klasse so zu strukturieren, dass ich eine Klasse mit Zusatzmethoden erstellen kann, die von der abstrakten Klasse abgeleitet wird und dann über die abgeleitete Klasse in zwei Unterzweigen weitere Methoden und Eigenschaften zur Verfügung stellt. In vereinfachter Form sieht das wie unten aus. Allerdings kann ich im Zweig M nicht auf Eigenschaften im Zweig P zugreifen und es stehen in der abgeleiteten Klasse keiner der beiden Zweige zur Verfügung.


public class toolabstrakt {
	public P p;
	public M m;
	public toolabstrakt() {
		p = new P();
		m = new M(ref p);
	}
}

public string Ver {
	get;
	set;
}


public class P {
	public string dateipfad {
		get;
		set;
	} //hier wird dann noch auf eine interne Variable verwiesen
	public string dateiformat {
		get;
		set;
	} //hier wird dann noch auf eine interne Variable verwiesen
}


public class M {
	P p;
	public M(ref P p) {
		this.p = p;
	}

	public string Convert() {
		string inhalt = File.ReadAllText(p.dateipfad);
		//...
	}
	//...
}

Wenn ich jetzt von der abstrakten klasse ableiten will kann ich nicht auf m oder p zugreifen. Selbst wenn ich davon noch Felder mit p{get;set;} und m{get;set;} dazu anlege.


public class mytool: toolabstrakt {
	p.dateipfad = "test.txt"; //geht nicht
	string werte = m.Convert(); //geht nicht
}

Ich hoffe ich konnte mein Problem verdeutlichen. Irgendwie stehe ich aufm Schlauch. Bitte aber keine Diskussion warum das ganze überhaupt strukturieren, etc.

Beste Grüße
Cornflake

Kannst Du mal beschreiben, was Du vor genau hast? Willst ne globale Klasse (Singleton) mit Settings machen, oder was genau soll das werden?
Gefühlt bist Du auf einem extremen Holzweg...

Und die Benennung Deiner Klassen und Eigenschaften tragen nicht gerade zum Verständnis und zur Übersicht bei 😉
[Artikel] C#: Richtlinien für die Namensvergabe

Hallo Abt

Ich versuche es mal genauer zu beschreiben, da ich eine allgemeine Lösung suche und bisher in den Microsoft Docs nur etwas mit verschachtelten Klassen und Namespaces gefunden habe, dass aber nicht ganz dem entspricht was ich vorhabe. Aktuell habe ich eine abstrakte Klasse mit einigen Methoden und Properties.


class abstrakt Dateikonverter {
	public string Quelldatei {
		get;
		set;
	}
	public string Zieldatei {
		get;
		set;
	}
	public string Konverterbeschreibung {
		get;
		set;
	}
	//... es folgen noch einige weitere Properties

	public void Laden() {
		// Verwendet Quelldatei und weitere Properties zum Laden der Datei
	}

	public void Konvertieren() {
		//Verwendet verschiedene Properties
	}

	//... Es folgend noch einige weitere Methoden
}

Von der oben genannten Klasse leite ich jetzt ab und erstelle einen Konverter für MaschineTyp1.

class Dateikonverter_MaschineTyp1: Dateikonverter,
IWerkzeuge,
IMaterial {
	Konverterbeschreibung = "R11,G09,03,L18";
	public Werkzeug tool1 {
		get;
		set;
	}

	//Es folgen noch weitere neu hinzugefügte Properties
	//Es kommen noch ein paar Methoden dazu.
	//Die Methoden benötigen teilweise Properties aus des Basisklasse und einer parallel dazu existierenden weiteren Zubehörklasse.
}

Jetzt ist das Problem, dass sich meine Methoden der abstrakten Klasse auf der selben Ebene befinden, wie die der fertig nutzbaren Klasse. Wenn ich die verwenden will gehen mir evtl. ein paar Methoden unter oder sie überschneiden sich vllt sogar vom Namen her.
Mein Ziel ist es das ganze zu strukturieren mit Ebenen.

Statt:


//...
void Vorbereiten() {
	Dateikonverter_MaschineTyp1 MaschineKT1 = new Dateikonverter_MaschineTyp1();
	MaschineKT1.Quelldatei = "testdaten.txt";
	MaschineKT1.Zielldatei = "RUU88.jy";
	if (MaschineKT1.tool1 == Werkzeuge.FR01) { //...}

		//Es folgen weitere Zugriffe auf verschiedene Properties immer überMaschineKT1.<Property>
	}
	//...
}

Ziel ist es die Zugriffe auf die Basis Properties in eine andere Ebene z.B. Default zu bringen.
z.B.


//...
void Vorbereiten() {
	Dateikonverter_MaschineTyp1 MaschineKT1 = new Dateikonverter_MaschineTyp1();
	MaschineKT1.Default.Quelldatei = "testdaten.txt";
	MaschineKT1.Default.Zielldatei = "RUU88.jy";
	if (MaschineKT1.tool1 == Werkzeuge.FR01) { //...}

		//Es folgen weitere Zugriffe auf verschiedene Properties die je nachdem ob es Standardeigenschaften/Methoden sind, z.B. über MaschineKT1.Default.<Property> erreichbar sind oder eben über MaschineKT1.<Property> wenn es individuelle Eigenschaften und Methoden sind.
	}
	//...
}

Ich hoffe das Problem wird klarer. Zudem kommt es vor, dass ich bei Strukturieren dann in Methoden von Dateikonverter_MaschineTyp1 auf Eigenschaften von Dateikonverter_ZuführungTyp2 zugreifen will. Also neben dem Default Zweig noch einen Zuführungszweig haben will der z.B. mit MaschineKT1.Zuführung.<Property> angesprochen werden soll.

Beste Grüße
Cornflake

Hallo,
vllt solltest du dich erst einmal mit der dynamischen Polymorphie und den Schlüsselwörtern virtual,new,override und base beschäftigen. Möglicherweise ist das eine bessere Lösung.

Nein ich will nicht mit new und overide bei Namensüberschneidungen arbeiten müssen und mit base kann ich zwar aus der abgeleiteten Klasse auf Eigenschaften der Basisklasse zugreifen aber nicht aus der Maschinenklasse auf die Zuführungklasse, da die ja nicht voneinander abgeleitet sind.

Naja.. wenn Du Dich nicht mit OOP beschäftigen willst; was sollen wir da noch sagen..? Im Prinzip ist das, worauf das hinaus läuft.
So wirklich nach OOP sieht das nämlich nicht aus. Hellsehen wird ein Compiler oder die Runtime halt nie können - Fortschritt der künstlichen Intelligenz hin oder her.

Mir geht es nicht darum mich nicht mit OOP zu beschäftigen. Ich habe nur vor die Eigenschaften und Methoden anders zu strukturieren, damit bestimmte Werte sich nicht überschneiden bzw. in einer langen Liste untergehen.

Wie würdet ihr es anstellen bestimmte Methoden/Eigenschaften in diesem Fall zu strukturieren. Habt ihr ein Quellcodebeispiel?

Naja, bei einer Sache wie if (MaschineKT1.tool1 == Werkzeuge.FR01) solltest Du ja dann mit Deinen OOP Kenntnissen sofort sehen, dass das kein valdier Weg sein kann.
Das kann spätestens in nen paar Monaten niemand mehr pflegen; von ordentlicher Testbarkeit mal ganz abzusehen.

Aber egal wie Du es drehst und wendest: der Compiler wird nicht hellsehen können.
Je länger ich aber nachdenke desto mehr erscheint mir - sofern ich es denn richtig verstehe - die Tatsache, dass das Grundkonstruktor evtl schon fischig ist.

Warum unterscheidest Du denn MaschinenTypen anhand der Klassennamen?
Das würde ja bedeuten, dass Du für jede Maschinenart eine Klasse hast - ist das wirklich Dein plan?
Und was das mit dem Default soll ist mir auch ein Rätsel, was ist der Sinn dahinter?

Ich verstehe den Sinn auch nicht. Und ich kann deiner Eklärung auch nicht folgen, wenn du z.B. von "Zweigen" redest. Der Code ist im Prinzip auch unlesbar. Schau dir mal [Artikel] C#: Richtlinien für die Namensvergabe an.

Was willst du denn erreichen, was mit den vorhandenen Settings nicht möglich ist? Werte kopieren und in einem anderen Setting ablegen?

Weeks of programming can save you hours of planning

Nagut ich hole weiter aus.
Die Microsoft Settings Klasse kann ich um eigene Werte(Eigenschaften) erweitern und dann die Konfiguration in einer Datei persistent ablegen. Die selbst hinzugefügten Eigenschaften sind bei der Settings Klasse gut strukturiert in dem App1.Default.<Eigenschaft> Zweig zu finden. Zusätzlich bietet die Klasse noch einige Methoden um die Eigenschaften zu laden und zu speichern. Allerdings hat die für meinen Bedarf ein großes Manko. Die Einstellungen werden als XML abgelegt und dann noch im Benutzerordner (je nachdem, ob es eine Benutzereinstellung oder Anwendungseinstellung ist). Ich habe dazu mir schon eine Lösung geschrieben, mit der ich die Einstellungen in einem individuellen Ordner serialisiert ablegen kann. Allerdings fehlt mir die Strukturierung wie bei der settings Version. Bei mir liegen die Eigenschaften in der gleichen Ebene wie die Methoden zum Speichern Laden, etc.

Daher ich würde von euch nur gerne wissen, wie kann ich so eine Strukturierung ordentlich bewerkstelligen. In der abgeleiteten Klasse sollen die neu hinzugefügten Eingenschaften, die zu serialisieren sind liegen und in den Unterzweigen die Methoden zum Laden ,Speichern, etc. und noch ein paar weitere Eigenschaften. Dabei würde ich gerne auch aus dem Unterzweig1 auf Eigenschaften vom Unterzweig2 der abstrakten Klasse zugreifen können.

Zum Schluss will ich wieder die abstrakte Klasse verwenden, die mir die Möglichkeiten bietet alle Werte der abgeleiteten Klasse zu serialisieren.

Zum Schluss will ich wieder die abstrakte Klasse verwenden, die mir die Möglichkeiten bietet alle Werte der abgeleiteten Klasse zu serialisieren.

Das geht nicht so ohne weiteres. Du kannst keine Attribute einer Instanz einer abstrakten Klasse lesen/setzen, wenn diese Eigenschaften nur in der Ableitung enthalten sind.
=> OOP.

PS: das Settingskonzept von .NET Framework wurde bereits seit längerem abgelöst.
> Microsoft.Extensions.Options

Allerdings hat die für meinen Bedarf ein großes Manko. Die Einstellungen werden als XML abgelegt und dann noch im Benutzerordner (je nachdem, ob es eine Benutzereinstellung oder Anwendungseinstellung ist).

Also ist das Problem, daß du selbst bestimmten möchtest, in welchem Ordner die Settings gespeichert werden?

Weeks of programming can save you hours of planning

@MrSparkle nein das habe ich gelöst. Nur hätte ich gerne die Klasse anders strukturiert. Dieses strukturieren hätte ich aber auch gerne generell besser verstanden.
Mit geht es um das zugreifen auf Methoden und Eigenschaften von anderen Zweigen aus und wie man die am besten Klassentechnisch erstellt. Bisher habe ich nur Namespace Verschachtelungen gefunden und Klasse in Klasse. Das wiederstrebt mir nur etwas. Da ich am liebsten je Datei nur eine Klasse haben würde.
Wie mache ich es, dass ich überhaupt richtig hinbekomme eine Klassenunterstruktur zu erstellen.
Also wie bei der MS Settingsklasse mit: App.Default.Eigenschaft. Bei mir ist das aktuell im Vergleich dazu App.Eigenschaft. Wie bekomme ich die Eigenschaft in einen Default Zweig in der Klasse bzw. wie müssen die Klassen verbunden werden, damit das so aussieht und sauber funktioniert bzw. zugreifbar ist.

Und wenn das richtig aufgebaut ist, wie kann ich dann in: Basisklasse.Unterklasse1.Methode1()
zugreifen auf: Basisklasse.Unterklasse2.Eigenschaft1()

@abt Danke für Link. Wird vmtl. nicht meine Lösung komplett ablösen können, aber vllt. für weitere Fälle doch eine Alternative sein.

Also wie bei der MS Settingsklasse mit: App.Default.Eigenschaft. Bei mir ist das aktuell im Vergleich dazu App.Eigenschaft. Wie bekomme ich die Eigenschaft in einen Default Zweig in der Klasse bzw. wie müssen die Klassen verbunden werden, damit das so aussieht und sauber funktioniert bzw. zugreifbar ist.

Wozu brauchst Du denn den Default "Zweig", was hast Du vor?
Ich glaube Du verstehst das "default" falsch....

Hallo,

Settings.Default ist keine Unterklasse, sondern nur eine statische Instanzeigenschaft:


internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
        
        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
        
        public static Settings Default {
            get {
                return defaultInstance;
            }
        }
}

Dies ist also so etwas wie eine Singleton-Variable (damit man von überall aus dem Projekt darauf zugreifen kann).
Ob daß design-technisch schön ist, muß jeder für sich selbst entscheiden.

Hi,

das Beispiel "App.Default.Eigenschaft" wirkt vielleicht ähnlich wie du es vorhast - ist es aber nicht im Geringsten.

Wenn du etwas ähnliches bauen wollen würdest, dann würde man das einen Singleton nennen. Wie man sowas ordentlich baut siehst du z.B. da: http://csharpindepth.com/articles/general/singleton.aspx
(ACHTUNG: Einen Singleton zu bauen ist in 99,9 % der Fälle kompletter Unfug)

Warum das ganze nicht vergleichbar ist:
Properties.Settings.Default, App.Default.Eigenschaft, etc. sind nicht wirklich dynamisch.
Hier werden automatisch C#-Klassen erstellt, welche genaue Ihre Eigenschaften kennen - das hat nichts mit abstrakten Klassen zu tun. Schon gar nicht mit verschiedenen Klassen. Wenn du dir nämlich die Singleton-Beispiele von oben anschaust wirst du feststellen, dass App und App.Default die selbe Klasse sind, wobei App die Klasse selbst ist - und die Default die statische Instanz der Klasse. (Das macht man um Ableitungen dieser Klasse unmöglich zu machen und zusätzlich leicht auf die einzig sinnvolle Instanz zugreifen zu können)
Nochmal: Wir reden nicht von einer abstrakten Klasse - sondern von einer versiegelten. Zusätzlich noch von einer statischen Instanz. Nichts davon hilft dir bei deinem Problem.

Das gesagt zu deinem eigentlichen Problem:
Wenn du Probleme hast Eigenschaften und Methoden in deinen Klassen zu unterscheiden - sind diese wahrscheinlich zu groß. (Single responsibility)

Ich sehe bei dir aktuell 2 Probleme:
a) Du willst einen Sammelplatz für Default-Einstellungen (den hast du ja scheinbar schon gelöst? Wenn nicht und's unbedingt sein muss hilft dir der Singleton-Artikel - würde ich aber auch eher mit DependencyInjection und Microsoft.Extensions.Configuration lösen)

b) Du willst auf die Eigenschaften und Methoden anderer Instanzen zugreifen
Letztendlich geht's hier aber um die Übergabe von Referenzen auf irgendwelche Klasseninstanzen. Dafür verwendet man wenn's so langsam unübersichtlich wird z.B. DependecyInjection. (Wobei ich nicht einmal sicher bin, ob du das brauchst)

Es ist doch praktisch kein Problem (auf Basis deines Beispiels) der Klasse MaschineTK1 z.B. im Konstruktor oder eben der "Vorbereiten"-Methode eine Referenz auf eine Instanz der Klasse ZuführungTyp2 zu geben 😕

LG

LG

Danke euch beiden, dass waren eigentlich die Antworten die ich mir erhofft hatte.
@Th69 Danke für den Code. Hab den noch nicht ganz verstanden. Werde dazu ein Tutorial suchen.
@Taipi88 Super Antwort.
Das Singleton Pattern hatte ich bisher eigentlich nur mit einer Mutaxe verwendet um zu verhindern, dass eine Winforms Anwendung mehrfach gestartet werden kann. Aber die 6 verschiedenen Arten die hier detailiert beschrieben werden kannte ich so noch nicht. Als nächstes kommt jetzt Microsoft.Extensions.Configuration reinlesen dran.
Wg b) ich werde es vmtl. mit Referenzierung auf Zuführung zu lösen versuchen. Hatte gehofft es gibt da noch einen andern Weg.
Hab inzwischen bemerkt, dass in meinem ursprünglichen Problem der Fehler war das p.dateipfad nicht geht, weil ich es nicht innerhalb einer Methode geschrieben hatte.

Danke für den Code. Hab den noch nicht ganz verstanden. Werde dazu ein Tutorial suchen.

Es geht darum, daß dort eine statische Eigenschaft verwendet wird. Wenn du dafür erst ein Tutorial suchen mußt, dann solltest du dir wirklich nochmal die Grundlagen anschauen, bevor du richtig loslegst.

ich werde es vmtl. mit Referenzierung auf Zuführung zu lösen versuchen

Was ist denn eine Referenzierung auf Zuführung? 😃
Ich würde empfehlen, die Begriffe aus der OOP zu verwenden, wenn es ums Klassendesign geht. Sonst reden wir die ganze Zeit aneinander vorbei, weil du von Zweigen und Zuführungen sprichst, und wir von Eigenschaften, Vererbung und generischen Klassen.

Weeks of programming can save you hours of planning