Laden...

"globale" Objekte

Erstellt von thoemy vor 19 Jahren Letzter Beitrag vor 19 Jahren 9.795 Views
T
thoemy Themenstarter:in
16 Beiträge seit 2005
vor 19 Jahren
"globale" Objekte

Hallo,

ich hoffe hier kann mir geholfen werden. Also mein Problem ist folgendes:

Ich hab zwei Objekte unterschiedlicher Klassen. Objekt1 soll auf Objekt2 zugreifen können (kein Problem) und Objekt2 soll auf Objekt1 zugreifen können (leider ein Problem). Objekt2 kennt nur die Klasse von Objekt1 sonst nichts.
Ich kenn mich mit C# noch nicht so gut aus und hab davor nur mir Delphi 😉 OO programmiert. Da hab ich das Problem einfach gelöst indem die zwei Objekte global deklariert waren. Würde ich ja in C# auch machen, wenn ich wüsste wie, falls das überhaupt geht.

Die Suche mit Google hat leider nicht geholfen, da ich nicht weiß nach was ich suchen soll und alle Tutorials die ich gefunden habe, dieses Problem nicht ansprechen.

Ich hab auch schon versucht das Objekt1 als Parameter Objekt2 zu übergeben ... leider alles erfolglos.

Thömy

4.207 Beiträge seit 2003
vor 19 Jahren

Hallo,

Dein Stichwort heißt "Singleton", dies ist ein Design Pattern, was exakt zur Lösung dieses Problems entwickelt wurde.

In Kürze erscheint ein Sonderheft des dotnet-Magazins zum Thema "ASP.NET", in dem ein Artikel mit einer Einführung zu Design Patterns enthalten sein wird, wo unter anderem das Singleton-Pattern beschrieben wird ... leider darf ich Dir den Artikel vor Heftveröffentlichung nicht zur Verfügung stellen, aber vielleicht schaust Du ihn Dir ja dann einmal an 🙂!

Bis dahin, such einfach mal bei Google nach "Singleton" ...

Viele Grüße,

Golo

Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de

T
thoemy Themenstarter:in
16 Beiträge seit 2005
vor 19 Jahren

Danke für die schnelle Antwort, mal sehen ob ich was finde.

4.207 Beiträge seit 2003
vor 19 Jahren

Was Du Dir mal anschauen kannst, ist http://msdn.microsoft.com/architecture/patterns/default.aspx?pull=/library/en-us/dnpatterns/html/Esp.asp ... da wird irgendwo in der Einleitung auch das Singleton wunderbar erklärt!

Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de

C
1.215 Beiträge seit 2004
vor 19 Jahren

das geht per reflection...
z.b. kann man so auf die eigenschaften von objekten zugreifen



using System.Reflection;
...
...
Type type = myObject.GetType();
MethodInfo method = type.GetMethod("ToString");
PropertyInfo property = type.GetProperty("eigenschaft");

string s = (string) method.Invoke(myObject, null);
s = (string) property.GetValue(myObject, null);


grtz
chief

T
thoemy Themenstarter:in
16 Beiträge seit 2005
vor 19 Jahren

Danke für die Antworten, aber irgendwie komme ich trotzdem nicht weiter. Ich werde mein Problem etwas anders beschreiben:

Ich hab zwei Formen, drückt man bei der ersten auf einen Button, dann soll sie verschwinden (Form1.Hide()) und die Zweite erscheinen (Form2.Show()). Das geht einwandfrei, nur soll jetzt, wenn ich Form2 schließe wieder Form1 erscheinen. Dies wäre ja kein Problem, wenn Form2 Form1 kennen würde, nur tut die das leider nicht.

Und die Sachen mit den Plattern und Reflection ist zwar schön und gut, aber ich kapiers nicht 😦. Und die Seitenlange Dokumentation von Microsoft ... naja ich hab nicht ewig Zeit 😉. Außerdem ist es ein Englisch mit vielen (für mich) nicht bekannten Wörtern.

Thömy

140 Beiträge seit 2004
vor 19 Jahren

Also hab das jetzt nur mal kurz überflogen, aber die Lösung deines Problems sieht so aus: Du machst aus den beiden Forms Singletons.

Singletons sind Instanzen einer Klasse die es in deinen Programm nur genau einmal gibt. Also von einer klasse Form1 gibt es auch nur genau ein Objekt Form1. Zugriff auf diese Objekte erfolgt über die Klassennamen und die statische Mehtode instance. Exisitiert die Instanz noch nicht, wird sie erstellt.

Hier der Code wie deine Form1 zu ändern ist, damit daraus ein Singleton wird:


	public class Form1 : System.Windows.Forms.Form
	{
		/// <summary>
		/// Erforderliche Designervariable.
		/// </summary>
		private System.ComponentModel.Container components = null;

		 private static Form1 instance;

		protected Form1()
		{
			//
			// Erforderlich für die Windows Form-Designerunterstützung
			//
			InitializeComponent();
			//
			// TODO: Fügen Sie den Konstruktorcode nach dem Aufruf von InitializeComponent hinzu
			//
		}

		// Methoden
		public static Form1 Instance()
		{
			// Uses "Lazy initialization"
			if( instance == null )
				instance = new Form1();

			return instance;
		}
//... Rest kann so bleiben

Entsprechend verfährt du mit Form2.

Außerdem musst du in Form1 noch den Aufruf anpassen.


		[STAThread]
		static void Main() 
		{
			Application.Run(Form1.Instance());
		}

Zugreifen kannst du nun auf die Objekte mit Form1.instance() und Form2.insance();

Also z.B. von deiner Form2 zurück auf Form1 mit


private void Form2versteckenUndForm1zeigen()
{		
		Form1.Instance().Show();
		Hide(); //form2 verstecken
}

Hoffe das passt so weit. Hab das jetzt größenteils aus dem Kopf gemacht. Ein relativ kurzer Link zu Singletons (nicht das du mir zu viel liest 🙂 ) , ist der hier:
http://www.dofactory.com/Patterns/PatternSingleton.aspx#_self1

Gruß,
Snowwolf

P
939 Beiträge seit 2003
vor 19 Jahren

Um das zu erreichen, muss nur Form1 die Form2 kennen. Form1 registriert sich fürs Closed-Ereignis von Form2 und kann sich so selbst wieder sichtbar machen.

public class Form1 : Form {
  
   private Button showForm2Button;
   private Form form2;

   private void InitializeComponent() {

      // [..]

      // ShowForm2Button
      showForm2Button = new Button();
      showForm2Button.Click += new EventHandler(HandeShowForm2Click);

      // Form2
      form2 = new Form2();
      form2.Closed += new EventHandler(HandleForm2Closed);
   }

   // Button geklickt, Form1 ausblenden, Form2 sichtbar machen.
   private void HandeShowForm2Click(object sender, EventArgs e) {
      this.Hide();
      form2.Show();
   }

   // Form2 wurde geschlossen, Form1 wieder anzeigen.
   private void HandeForm2Closed(object sender, EventArgs e) {
      this.Show();
   }
}

Gruss
Pulpapex

T
thoemy Themenstarter:in
16 Beiträge seit 2005
vor 19 Jahren

Nochmals danke. Ich werde das warscheinlich so machen wie Snowwolf3000.

an Pulpapex:

Ich glaub das ist nicht so ganz die optimale Lösung, da beide Formen in einer Datei liegen und somit nich so schön editiert werden können.

49.485 Beiträge seit 2005
vor 19 Jahren

Hallo thoemy,

Form2 braucht Form1 für das, was du willst auch nicht zu kennen! Schau stattdessen mal hier: Eigener Observer insbesondere meinen Beitrag vom 17.03.2005 14:00. Form1 könnte bzw. würde sich nach der Benachrichtung der Änderung selbst wieder anzeigen.

herbivore

PS: Singeltons sind hier sicher keine optimale Lösung. Der - auch von Pulpapex - vorgeschlagene Observer-Pattern ist hier das Mittel der Wahl.

4.207 Beiträge seit 2003
vor 19 Jahren

Ein Mediator wäre IMHO auch eine Möglichkeit, oder?

Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de

T
thoemy Themenstarter:in
16 Beiträge seit 2005
vor 19 Jahren

Ich hab mich jetzt für die Singleton Variante entschieden, da es bis jetzt das einzigste ist was ich verstehe. Was hier jetzt die optimale Lösung ist, ist mir egal, da es kein perfektes Programm werden soll. Es ist einfach ein Spiel als Projekt für die Schule. Es muss nur funktionieren, wie ist egal, da sowieso kein Lehrer von uns C# kann 🙂.

Ich hab jetzt allerdings noch ein Problem:

Form1 zeigt Form2 an und versteckt sich. Beim Schließen von Form2 zeigt sich Form1 wieder. Wunderbar! Nur wenn ich jetzt wieder Form2 anzeigen will kommt:

Eine nicht behandelte Ausnahme des Typs 'System.ObjectDisposedException' ist in system.windows.forms.dll aufgetreten.

Zusätzliche Informationen: Auf das verworfene Objekt "Playingfield" kann nicht zugegriffen werden.

So wie ich das verstehe exisitiert Form2 nicht mehr. Ist ja eigentlich egal, da es sich doch selber wieder erstellen soll. Nur leider ist die Bedingung "if( instance == null)" nicht wahr.

Ich hoffe ihr könnt mir diesmal auch so schnell helfen.

Thoemy

49.485 Beiträge seit 2005
vor 19 Jahren

Hallo thoemy,

in dem EventHandler HandleForm2Closed aus Pulpapex Vorschlag könntest du instance auf null setzen und dann würde die Abfrage funktionieren.

herbivore

140 Beiträge seit 2004
vor 19 Jahren

@thoemy
Kann deinen Fehler nicht so recht nachvollziehen. Was ist den "Playingfield" überhaupt?
Auf jedendefall wird bei einen Singleton eigentlich die Instanz nicht verworfen. Ist ja der Sinn bei der Sache. Nur beim ersten Aufruf wird das Objekt erstellt und danach wird eine Instanz darauf behalten.

Hier einfach mal ein Prog was das macht was du willst.
http://mitglied.lycos.de/xyz001100/FormsMitSingleTon.zip

Also bei mir geht es soweit, ob das jetzt die beste Lösung ... keine Ahnung 🙂
Und damit kommen wir zu herbivore:

@herbivore
Was spricht den gegen eine Lösung über Singletons?

1.373 Beiträge seit 2004
vor 19 Jahren

Original von Snowwolf3000
@herbivore
Was spricht den gegen eine Lösung über Singletons?

Weil es absolut nicht den Hauch einer Notwendigkeit und/oder Sinnhaftigkeit gibt, hier einen Singleton einzusetzen. Singletons werden dann benutzt, wenn es nur eine (1) Instanz einer Klassen geben darf. Leider wird das Singleton in viel zu vielen Fällen als Ersatz für globale Variablen missbraucht, wie in diesem Fall. Klar kann man damit ein Objekt global verfügbar machen, aber warum sollte es in diesem Fall nur eine Instanz von Form1 und Form2 geben? Ganz davon zu schweigen, dass das Design mit Singletons ziemlich schlecht zu warten wäre. Was ist, wenn noch etwas anderes geschehen soll, wenn Form2 schließt? Dann muss in Form2 wohlmöglich der Quellcode angepasst werden, obwohl Form2 im Grunde genommen nichts damit zu tun hat... Dann doch lieber über die events, wie von Pulpaplex und herbivore vorgeschlagen. Form2 muss ja nichts davon mitkiegen, dass jemand daran interessiert ist, wann sie schließt.

Mir läuft es immer ein bisschen kalt den Rücken herunter, wenn das Wort Singleton in die Runde geworfen wird 😉 Es gibt eigentlich nicht sehr viele Anwendungsgebiete für Singletons; zumindest gibt es fast immer elegantere Lösungen.

Zum Thema "Singletons und global erreichbare Objekte": http://gentlestorm.de/blog/articles/180.aspx

MfG VizOne

T
thoemy Themenstarter:in
16 Beiträge seit 2005
vor 19 Jahren

@Snowwolf3000:

Deine Version des Programmes versagt auch, wenn man Form2 nicht über den Button sondern über das "X" schließt.

@VizOne, herbivore und Pulpapex:

Wenn ich die anderen Lösungen verstehen würde, dann würde ich sie nehmen.

Ich bin auch grad etwas überfragt, wie ich das mit meinem Klassen regeln soll. Momentan sind alle Singletons 😉, was aber nicht notwendig wäre. Ich weiß nur leider nicht, wie ich Klassen nur bestimmten anderen Klassen zur verfügung stelle.

Thömy

140 Beiträge seit 2004
vor 19 Jahren

Also wenn du Form2 über x schließt müsstest du halt die Anwendung beenden oder Form1 wieder zeigen (und das halt in Closed von Form2 reinschreiben). Was du halt da machen willst.

Allerdings muss ich den Anderen schon recht geben: Singletons sind wirklich keine optimale Lösung dafür.

49.485 Beiträge seit 2005
vor 19 Jahren

Hallo zusammen,

@Snowwolf3000

@herbivore
Was spricht den gegen eine Lösung über Singletons?

Das was VizOne geschrieben hat, kann ich nur unterstreichen und auch nichts weiter hinzufügen. Ich könnte nur versuchen, es in einen Satz zu bringen:

In der objektorientierten Programmierung gibt es absichtlich keine globalen Variablen; man sollte sie daher nicht per Singelton über die Hintertür wieder einführen.

@thoemy

@VizOne, herbivore und Pulpapex:
Wenn ich die anderen Lösungen verstehen würde, dann würde ich sie nehmen.

Das Verstehen erzwingen können wir natürlich nicht 🙂 aber wir beantworten gerne (konkrete) Fragen. Außerdem ist der Code von Pulpapex doch quasi direkt verwendbar.

herbivore

T
thoemy Themenstarter:in
16 Beiträge seit 2005
vor 19 Jahren

Hab jetzt alles brav ohne Singletons 😉 Und alles funktioniert (bis jetzt) wunderbar ... Danke!

Thoemy

4.207 Beiträge seit 2003
vor 19 Jahren

Dass ich den Begriff "Singleton" in den Raum geworfen habe, war auch mehr die Antwort auf "Wie realisiere ich eine globale Variable in einer OOP-Umgebung", als die Lösung auf dieses konkrete Problem ...

Ob hier ein Singleton angebracht ist, steht sicherlich auf einem anderen Blatt.

Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de