Laden...

Objekt als Dictionary-Schlüssel - neues Objekt ist anderes (trotz gleicher Werte)

Erstellt von Frokuss vor 6 Jahren Letzter Beitrag vor 6 Jahren 3.988 Views
F
Frokuss Themenstarter:in
158 Beiträge seit 2015
vor 6 Jahren
Objekt als Dictionary-Schlüssel - neues Objekt ist anderes (trotz gleicher Werte)

Guten Abend,

ich habe da einmal eine Verständnisfrage...

Und zwar erzeuge ich ein Objekt (MyPair_I_B) und verwende das als Schlüssel in einem Wörterbuch. Wenn ich nun aber das Objekt neu erzeuge (mit gleichen Werten), scheinen die beiden Objekte verschieden zu sein.
Soweit ich verstanden habe, könnte ich mittels Equal prüfen ob sie gleich sind...

Aber meine Frage ist:
Warum sind die verschieden?
Wie kann ich denn geschickt prüfen ob, das Objekt als SChlüssel im Wörterbuch vorhanden ist?

folgendes Objekt habe ich:


	public class MyPair_I_B
	{
		public int id;
		public bool isGroup;
		
		public MyPair_I_B(int id, bool isG){
			this.id = id;
			isGroup = isG;
		}
	}


Dictionary<MyPair_I_B, int> myDic = new Dictionary<MyPair_I_B, int>();
myDic.Add(new MyPair_I_B(5, false), 123);

MyPair_I_B MPIB = new MyPair_I_B(5, false);

//unschön		
foreach(KeyValuePair<MyPair_I_B, int> test in myDic){
	if(test.Key.id == to && test.Key.isGroup == b){
		//Schlüssel vorhanden
		break;
	}

	if(test.Key.Equals(MPIB)){//Quasi das gleich
		//Schlüssel vorhanden
		break;
	}
}

//wünschenswert - aber kommt false raus O.o
if(myDic.ContainsKey(MPIB))
	//Schlüssel vorhanden

Ich hoffe ihr könnt mir da weiterhelfen?

Besten Gruß Frokuss

D
261 Beiträge seit 2015
vor 6 Jahren

In deiner Klasse MyPair_I_B müssen die Methoden GetHashCode und Equals überschrieben werden.
Equals muss so implementiert werden, dass es true zurückliefert wenn du die verschiedenen Instanzen (aber gleichen Properties) vergleichst. GetHashCode muss für beide Instanzen den gleichen Integer Wert zurückliefern.

Lies dir hier mal den "Remarks" Abschnitt durch: MSDN - Object.GetHashCode Method (System)
siehe auch: MSDN - Guidelines for Overriding Equals() and Operator ==

Alternativ kannst du auch die IEqualityComparer<T>-Schnittstelle implementieren und beim Erstellen deines Dictionaries übergeben.

16.834 Beiträge seit 2008
vor 6 Jahren

Du vergleichst Referenzen und keine Inhalte; und die Referenzen sind einfach unterschiedlich.
Werte- vs. Referenztypen

T
461 Beiträge seit 2013
vor 6 Jahren

@dannoe, also echt, in dem Fall ist dein Vorschlag doch viel zu umständlich. Es reicht wie @Abt schon erklärte den Inhalt der Referenz anstatt die Referenz selbst zu vergleichen...

Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen... 😄

D
261 Beiträge seit 2015
vor 6 Jahren

In seinem Kommentar steht, dass er gerne dictionary.ContainsKey verwenden würde. In dem Fall wäre das aber die einzige Möglichkeit oder?

Die Lösung mit einem Wertevergleich hat er ja selbst schon gepostet.

T
2.224 Beiträge seit 2008
vor 6 Jahren

@dannoe
Wenn man mit ContainsKey arbeiten will, dann muss man Equals + GetHashCode implementieren.
Hier verwendet das Dictionary einen Comparer um den Hash Code zu ermitteln und dann auch per Equals zu prüfen ob die beiden Objekte trotz gleichem Hash Code identisch sind.

Hier muss man mal einen Blick in die Doku werfen.
Ich selbst war bisher auch nicht in der Situation diesen Fall abzudecken.
Entsprechend sollte man mal schauen ob es in der Doku Beispiele o.ä. dafür gibt.

Die Frage wäre aber, ob es wirklich nötig ist diesen Ansatz umzsetzen?
Wozu gibt es doppelte Objekte mit gleichen Werten aber unterschiedlichen Referenzen?
Handelt es sich dabei nur um Kopieen?
Wenn ja, wäre es möglich notfalls diese vor dem arbeiten mit dem Dictionary zu vermeiden?
Gerade bei einer Klasse mit 2 Properties würde es sich doch anbieten, die ID als Key und das Bool feld als Value im Dictionary zu speichern.
Dann sparst du dir doppelte Objekte um damit auch Speicher.
Dann brauchst du dir auch im die Implementierung eines Comparers keine Gedanken machen.

Nachtrag:
Welchen Wert bildest du in deinem Code Beispiel mit dem Value im Dictionary ab?
Wäre dies nicht eine Mglichkeit dies im Objekt selbst zu speichern?
Dann könntest du die ID deines Objekts als Key und das Objekt selbst als Value speichern?
Oder gibt es den Fall, dass du doppelte IDs hast?
Dann wäre aber Dictionary mit dieser Klasse als Key ein sehr komischer Fall, da du keine Vorteile daraus ziehen könntest außer doppelte Werte aller Eigenschaften der Klasse abzufangen.
Ob dies dann aber ein Fall für das Dictionary ist, ist mir noch nicht ganz klar.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

16.834 Beiträge seit 2008
vor 6 Jahren

Ich verstehe den Kontext so, dass er aus Unwissenheit gerne Contains verwenden würde, da er Referenz vs. Wert hier nicht erkennt.
Daher auch seine Frage

Warum sind die verschieden?
Wie kann ich denn geschickt prüfen ob, das Objekt als SChlüssel im Wörterbuch vorhanden ist?

Er sagt mit keinem Wort, dass er unbedingt Contains verwenden will.
Sehe also keinen Grund hier so n Aufstand zu machen 😉

T
2.224 Beiträge seit 2008
vor 6 Jahren

@Abt
Wenn es nur daran liegt, dass hier ein Grundverständnis zum Thema Referenz- und Wertetypen fehlt, dann ist die Sache relativ simpel.

Aber mich beschleicht, dass darauf dann auch ein besserer Lösungsansatz als jetzt folgen wird.
Entsprechend würde ich auch das Problem bei der Umsetzung mit dem Dictionary auch gleich lösen wollen.
Aber mal schauen was noch kommt.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

16.834 Beiträge seit 2008
vor 6 Jahren

Ich bin der Meinung einen Referenztyp wie einen Wert-Typ aussehen zu lassen, birgt immer eine Gefahr; vor allem wenn man nicht 101% weiß, was man tut.
Die vielen Dutzend Fragen von Dir machen es zudem etwas undurchsichtig, finde ich....

F
Frokuss Themenstarter:in
158 Beiträge seit 2015
vor 6 Jahren

Cool Leute 😄

Wie ich sehe sollte ich auf den Kontext eingehen... Ich schreibe gegenwärtig eine Chatanwendung, bei der es Single-Chats und Gruppen-Chats gibt. Und wie T-Virus geschrieben hat, gibt es bei mir doppelte IDs. Daher User-ID und Gruppen-ID. Ich verwende daher den bool nur um die IDs zu differenzieren.
Mein Dictionary-Value ist in meinem Fall dann ein eigenes Objekt, welches den kompletten Chat enthält. Er unterscheidet sich nicht bei den beiden Chat-Varianten.

Ich bin leider noch nicht dazu gekommen, den Ansatz von dannoe zu testen... Aber scheint ja auch etwas schwieiger zu sein, zumindestens das mit dem HashWert.

Ich werde mich mal in den Literatur einlesen und mich dann noch mal dazu melden.

Danke euch aber schon mal für den regen Diskuss 😃

Gruß Frokuss

Nachtrag:
Um das ganze zu sehen, hier einmal der Ausschnitt aus meinem Worker-Thread:


			Dictionary<MyPair_I_B, Data_Nachrichten> tempChatKomplett = new Dictionary<MyPair_I_B, Data_Nachrichten>();
			if(tempMess.Count > 0){
				foreach(MyMessagePair m in tempMess){
					int chatId;
					MyPair_I_B MPIB;
					
					if(m.id.Equals(thisUser.id))
						chatId = m.to;
					else
						chatId = m.id;
					
					MPIB = new MyPair_I_B(chatId, m.isG);
					foreach(KeyValuePair<MyPair_I_B, Data_Nachrichten> check in tempChatKomplett){
						if(check.Key.Equals(MPIB)){
							MPIB = check.Key;
							break;
						}
					}
					
					//MyMessagePair: from, to, txt, time, readed
					if(!tempChatKomplett.ContainsKey(MPIB)){
						tempChatKomplett.Add(MPIB, MyXMLMessage.Load(m.id, m.to, false));
						//MessageBox.Show(tempChatKomplett[3].time[0] + " # " + m.now);
					}
					
					if(!tempChatKomplett[MPIB].time.Contains(m.now))
						tempChatKomplett[MPIB].Add(m.id, m.to, m.txt, m.now, m.readed);
				}
			}
F
Frokuss Themenstarter:in
158 Beiträge seit 2015
vor 6 Jahren

Also ich habe mir das nun mal angeguckt...

Verbessert mich bitte! Ich verwende GetHashCode um eine schnellere Variante zu haben als Equal?

Ich glaube diese Methode bringt mich so nicht weiter. Folgendes habe ich aber aus der Equals-Methode gemacht:

		public bool Equals(MyPair_I_B v){
			return id.Equals(v.id) & isGroup.Equals(v.isGroup);
		}

Auch diese scheint überflüssig zu sein, da ich sie nicht überschreiben muss...

Bin nen bischen verwirrt.

Besten Gruß Frokuss

T
2.224 Beiträge seit 2008
vor 6 Jahren

@Frokuss
Klingt für mich nicht sinnvoll.
Hier die Ids zu mischen, macht die Programmierung nicht einfacher für dich.
Du solltest Gruppen und Benutzer trennen.
Ein Benutzer, sollte dann eine Liste mit Gruppen zu denen er gehört, haben.

Somit wäre auch dein aktueller Versuch mit der Zuordnung der Nachricht zum Benutzer oder der Gruppe sauberer umgesetzt und ist später einfacher zu verstehen.
Du schaffst dir mit dem vermischen der IDs nur zusätzliche Komplexität.

Ebenfalls wäre es hilfreich eindeutige IDs zu nehmen, spart dir doppelte IDs und spätere Zuordnungsfehler.
Hier wäre dann eine Guid hilfreich um jedem Benutzer und jeder Gruppe eindeutige IDs zu geben.
Somit kannst du nie den Fall haben, dass es doppelte IDs gibt, egal ob bei Benutzern oder Gruppen.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

16.834 Beiträge seit 2008
vor 6 Jahren

Ich bezweifle, dass bei dem Code hier der "Geschwindigkeitsvorteil" von GetHashCode eine Rolle spielt...
Mach's lieber richtig. 👍

F
Frokuss Themenstarter:in
158 Beiträge seit 2015
vor 6 Jahren

Ich habe tatsächlich alle Daten sauber getrennt. Nur die Chats habe ich wegen der gleichen Struktur zusammen gefasst. Die Daten vom Client kommen dabei aus der Datenbank und werden automatisch incrementiert.
Im Data objekt erkenne ich auch ob es ein Gruppen oder Freundeschat ist. Und der Chat funktioniert akzuell auch so wie ich den erstellt habe. Der Server erhält dann saubere Daten und kann die dann weiter schicken an die anderen Clients.

@Abt... wie meinst du das mit richtig machen? Geschwindigkeit kann ich denke ich wirklich vernachlässigen... das ganze passiert ja nur beim absenden einer Nachricht (im Chat Fenster).

Gruß Frokuss

5.658 Beiträge seit 2006
vor 6 Jahren

Hi Frokuss,

wenn du sowieso eine eindeutige ID hast, dann kannst du die auch gleich als Schlüssel für das Dictionary verwenden.

Wenn du Gruppen und Nachrichten hast, die die gleiche ID besitzen können, dann verwende jeweils ein Dictionary für die Nachrichten und eins für die Gruppen. Es gibt eigentlich keinen Grund, beides im gleichen Dictionary zu speichern, wenn es sowieso unterschiedliche Daten sind.

Weeks of programming can save you hours of planning

F
Frokuss Themenstarter:in
158 Beiträge seit 2015
vor 6 Jahren

Hallo MrSparkle,

vielen Dank für deine Antwort 😃 Ich glaube ich muss noch einmal ein wenig ausholen...

1.) Alle Daten kommen aus der Datenbank. Dabei werden die Daten der User in einer Tabelle incrementiert und die Daten der Gruppen in einer anderen Tabelle incrementiert. Daher: User-ID und Gruppen-ID ++könnten ++identisch sein.

2.) Diese Daten liegen (noch) sauber getrennt beim Client vor.

3.) Im Chat-Fenster verschmelzen die Daten teilweise - da ich mit verschiedenen Tabs zu den Chats arbeite.

Jede Nachricht ist ein eigenes Object mit folgenden Attributen:

		public int id;//Absender
		public int to;//Empfänger - Anwender oder Gruppe
		public long now;//Absendezeit
		public string txt;//inhalt
		public bool readed;
		public bool isG;//true = Gruppe; false = Anwender

Dieses Object muss irgendwie zum Server kommen - und beim Client muss ich dieses identifizieren und im richtigen Bereich einfügen (Interface & in den Variablen). Wenn ich nun mit zwei Vaiablen anstelle von einer arbeite, muss ich also quasi alle Methoden doppelt haben - und es ist nur wenig verschieden... Deswegen wollte ich nur ein Dictionary haben.

D
985 Beiträge seit 2014
vor 6 Jahren

Wenn zwei sich unterhalten, dann könnte man das auch schon als Gruppe ansehen.

Will damit sagen, man kann die Verwaltung (Gruppen-Chat oder Zweier-Chat) komplett gleich halten und benötigt keine Fallunterscheidung.

5.658 Beiträge seit 2006
vor 6 Jahren

3.) Im Chat-Fenster verschmelzen die Daten teilweise - da ich mit verschiedenen Tabs zu den Chats arbeite.

Diese Aussage ergibt einfach keinen Sinn. Für mich sieht es eher danach aus, daß dein Datenmodell nicht durchdacht ist, bzw. nicht den eigentlichen Anforderungen entspricht.
Mir ist auch nicht so richtig klar, an welcher Stelle man in einer Chat-Anwendung überhaupt ein Dictionary benötigt.

Weeks of programming can save you hours of planning

T
2.224 Beiträge seit 2008
vor 6 Jahren

@MrSparkle
Er braucht es vermutlich, wenn jemand X Chats offen hat um dann zu schauen an welchen Benutzer/Gruppe die aktuelle Nachricht gehen soll.
Mit einem sauberen Ansatz wäre dies wahrscheinlich nicht mal nötig.

Hier müsste man doch schon die Teilnehmer kennen, wenn man im entsprechenden Tab ist.
Jeder Tab müsste ja schon den Empfänger(Gruppe/Benutzer) kennen.
Wenn ich dann eine Nachricht sende, müsste die Zuordnung schon da sein.
Entsprechend ist mir der aktuelle Aufwand nicht ganz klar.

Wenn dies aber nun auf Serverseite geschieht, sehe ich durch die Increments schon Probleme durch Fallunterscheidung zwischen Benutzer und Gruppe.
Da die Nachricht bei einer Gruppe nochmal an Benutzer der Gruppe geschichkt werden muss, hat man durch doppelte IDs schon genug Probleme.

Ich bin mit dem aktuellen Ansatz nicht zu frieden, weshalb ich in diesem Fall die Increments verwerfen und auf Guids setzen und auch die Gruppen und Benutzer direkt trennen würde.

Dann kann man mit einem Gruppen und einen Benutzer Dictionary die Empfänger finden und muss keine doppelten IDs fürchten.
Aber selbst dann wäre es noch unschön gelöst, da man eben den Empfänger noch suchen muss obwohl er bekannt sein müsste.

Hier wäre es sinnvoll, wenn der Client dem Server direkt mitteilt, welchem Benutzer/Gruppe er eine Nachricht schicken will.
Der Client sollte dies, bei einem sauberen Aufbau schon wissen und müsste nicht er suchen.
Wenn ich einen Chat starte oder einen bestehenden wieder öffne, sollte klar sein welcher Benutzer oder Gruppe ich Nachrichten schicken will.
Deshalb ist mir nicht ganz klar warum dies hier nochmal ermittelt werden muss.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

5.658 Beiträge seit 2006
vor 6 Jahren

Er braucht es vermutlich, wenn jemand X Chats offen hat um dann zu schauen an welchen Benutzer/Gruppe die aktuelle Nachricht gehen soll.

Wenn das tatsächlich so ist, dann bindet man das ViewModel des aktuellen Chats an die SelectedItem-Eigenschaft des TabControls, und ruft dann das Command zum Senden der Nachricht in diesem ViewModel auf.

Edit:

  
  				MPIB = new MyPair_I_B(chatId, m.isG);  
  				foreach(KeyValuePair<MyPair_I_B, Data_Nachrichten> check in tempChatKomplett){  
  					if(check.Key.Equals(MPIB)){  
  						MPIB = check.Key;  
  						break;  
  					}  
  				}  
  

Wenn ich mir den Code so anschaue, dann empfehle ich doch erstmal einen Blick in die Links aus [FAQ] Wie finde ich den Einstieg in C#?.

Weeks of programming can save you hours of planning

F
Frokuss Themenstarter:in
158 Beiträge seit 2015
vor 6 Jahren

Huch...
Ich fange vielleicht mit den anforderungen noch einmal an...

1.) Wenn der Anwender abwesend ist, muss er zu einem späteren Zeitpunkt die Nachrichten erhalten

  • Deswegen geht die Kommunikation über den Server (immer)
    2.) Um nicht immer und immer wieder die gleichen Nachrichten zu übertragen, werden die Nachrichten lokal (Client) abgespeichert
  • Das findet zum einen unmittelbar nach der Synchronisation statt
  • Und wenn das Chat-Fenster geschlossen wird (damit nicht bei jeder Nachricht gespeichert wird)
    • Jeder Chat landet dabei in einer eigenen Datei

Aus zweitens folgt eigentlich, dass ich also noch zu einem späteren Zeitpunkt an den Chat heran muss. Da wollte ich mir nicht die Mühe machen, die Chat-Chronik zu durchforsten (insbeonsders, weil ich mit Win.Forms arbeite und RichTextBox nicht in frage kommt).

Der Ablauf des sendes ist dann wie folgt:
1.) Anwender drückt Enter
2.) Workersthread holt sich die Nachricht ab und sendet das zum Server
3.) Der Server bestätigt den Empfang
4.) Die Nachricht wird erst dann in den Chat eingefügt. (Mir fehlt noch ein Mechanismus zum erneut senden der Nachricht)

Deswegen brauche ich also Temporäte Dictionarys, da es theoretisch passieren kann, dass der Anwender in einem anderen Chat-Tab ist, bevor die Nachricht bestätigt wurde.

Und so regel ich das ganze beim Server (Bestandteil aus dem Thread, der für jede Verbindung erzeugt wird):


						else if(nachricht.cmd.Equals(CMD.AddNachricht)){
							MyMessagePair mmp = new MyMessagePair(nachricht.werte);
							while(ms._isWriting)//Neu
								Thread.Sleep(2);
							lock(_lockMS){

								ms.Senden(CMD.OkNachricht, mmp.now.ToString());
								AddMessage(new MyMessagePair(nachricht.werte));//in DB speichern
								
								if(!mmp.isG){//Keine Gruppe
									if(anwenderID.ContainsKey(mmp.to))
										anwenderID[mmp.to].IncommingCMD(CMD.NeuNachricht, mmp);									
								}
								else{ //Gruppe
									List<int> member = GetGruppenMember(mmp.to);//komt aus der DB - theoretisch
//könnte ich das auch temporär speichern, solange der Anwender verbunden ist...
									foreach(int i in member){
										if(anwenderID.ContainsKey(i)){
											if(i != userID)
												anwenderID[i].IncommingCMD(CMD.NeuNachricht, mmp);//In anderen Thread schieben
										}
									}
								}
							}
						}

5.658 Beiträge seit 2006
vor 6 Jahren

Da wollte ich mir nicht die Mühe machen, die Chat-Chronik zu durchforsten (insbeonsders, weil ich mit Win.Forms arbeite und RichTextBox nicht in frage kommt).

Die UI ist doch nur für die Anzeige der Daten zuständig. Du scheinst hier aber die Anzeige und die Geschäftslogik zu vermischen. Für die Verwaltung deiner Chats ist jedenfalls die BL und nicht die UI zuständig. Ob du eine RichTextBox oder beliebige andere Steuerelemente für die Anzeige verwendest, ist doch dabei völlig egal. Siehe dazu [Artikel] Drei-Schichten-Architektur.

Deswegen brauche ich also Temporäte Dictionarys, da es theoretisch passieren kann, dass der Anwender in einem anderen Chat-Tab ist, bevor die Nachricht bestätigt wurde.

Du kannst doch die Gruppe, in der die Nachricht gesendet wurde, zusammen mit der gesendeten Nachricht speichern. Da jede Nachricht eine Gruppe (bzw. einen Chat) braucht, gehört diese Information zur Nachricht dazu. Diese Zuordnung über ein Dictionary herzustellen, halte ich für unnötig kompliziert.

Zu deinem geposteten Code kann ich leider nichts sagen, der ist nahezu unlesbar und unverständlich für Außenstehende. Du solltest versuchen, zuerst ein geeignetes Datenmodell für deine Anwendung zu entwerfen, und dann die Logik strukturiert und systematisch in den entsprechenden Klassen der BL zu implementieren. Nur so hast du am Ende Code, den du testen kannst, und den du auch nach ein paar Monaten noch verstehst.

Weeks of programming can save you hours of planning

T
2.224 Beiträge seit 2008
vor 6 Jahren

Ist zwar wieder ein paar Tage her, aber mir kam dazu Gestern noch eine mögliche Lösung.
Wäre es vielleicht machbar eine Session zu implementieren um die eindeutige Zuordnung zu bekommen?

Also z.B. dass der Client dem Server beim Beginn des Chats mitteilt, mit welchem User/Gruppe er chatten will.
Der Server legt dann die Session an und merkt sich diese mit einer eindeutigen ID(Guid).
Somit musst du beim senden der Nachricht nur die Session ID mitteilen.
Der Server kann dann darüber den Empfänger/Gruppe ermitteln.
Nachrichten an die Gruppe kann er dann wiederum über die aktuellen Teilnehmer der Gruppe senden.

Wenn die Session vorbei ist, z.B. in dem der Benutzer den Tab oder die Anwendung schließt, muss der Client dem Server nur das Ende der Session mitteilen.
Dann kann dieser die gespeicherte Session verwerfen.

Bsp. für deine Session Klasse


public class Session
{
	// Guid der Session
	public Guid Guid { get; set; }
	
	// Zeitstempel wann die Session gestartet wurde
	public DateTime Startzeit { get; set; }
	
	// Zeitstempel wann die Session beendet wurde
	// Ist diese offen, dann ist dies DateTime.MinValue
	public DateTime Endzeit { get; set; }
	
	// Absender ID (Benutzer)
	public MyPair_I_B Absender { get; set; }
	
	// Empfänger ID(Benutzer/Gruppe)
	public MyPair_I_B Empfaenger { get; set; }
}

Somit kennt dein Server den Absender sowie den/die Empfänger bei dieser Sitzung.
Der Client muss dann nur noch die Nachricht + Session Guid senden.
Die Zuordnung kannst du dann über die Session ID ermitteln.

Die Informationen kannst du dann in einem Dictionary<Guid, Session> speichern und über diese auch abfragen.
Die Ersparnis dabei ist, dass du nicht bei jeder Nachricht den Empfänger ermitteln musst.
Den der Client und Server wissen über die Session wer die aktuelle Nachricht bekommen soll und von wem diese stammt.

Deine Sessions sollten dann aber, um nicht den Server zu flutten, eine Lebensdauer haben und alte Sessions auch entfernt werden.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

16.834 Beiträge seit 2008
vor 6 Jahren

Also z.B. dass der Client dem Server beim Beginn des Chats mitteilt, mit welchem User/Gruppe er chatten will.
Der Server legt dann die Session an und merkt sich diese mit einer eindeutigen ID(Guid).
Somit musst du beim senden der Nachricht nur die Session ID mitteilen.

Das heisst der Server soll blind den IDs des Clients vertrauen und die Verantwortung der Logik an den Client abgeben?
Ein ziemliches Nogo.

T
2.224 Beiträge seit 2008
vor 6 Jahren

Die Authentifizierung muss natürlich immer erfolgen, unabhängig von den Aktionen.
Sollte ja jetzt auch schon der Fall sein.
Sonst könnte man jetzt schon mit zufälligen Daten Nachrichten an jeden senden.
Ich bin davon ausgegangen, dass dies bisher auch schon der Fall ist.
Hier muss aber der TE noch Details liefern und vielleicht auch prüfen ob diese Lösung ihm weiterhelfen würde.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

16.834 Beiträge seit 2008
vor 6 Jahren

Wenn der Server nicht die IDs verwaltet, dann kann er auch dessen Legitimität nicht prüfen.
Das ist also somit eine Sackgasse.

T
2.224 Beiträge seit 2008
vor 6 Jahren

Natürlich soll der Server die IDs verwalten.
Die Session wird beim Server gestartet und der Client bekommt dann nur die Session ID.
Der Client muss dann die Nachricht + Session ID senden damit der Server diese den richtigen Empfänger zustellen kann.
Der Server kann dann die Nachricht über die Session Informationen den Empfänger zuordnen.

Der Client kennt dann im aktuellen Chat Tab nur seine Session ID.
Verstehe also nicht ganz, wie das Konzept bei dir aussieht.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

D
985 Beiträge seit 2014
vor 6 Jahren

Was für ein Problem mit diesem Session-Objekt gelöst werden soll ist mir schleierhaft.

Eine Unterhaltung kann doch zwischen 2 (eigentlich auch 1) bis n Benutzern stattfinden. Die Unterhaltung selber ist technisch nicht anders, wenn diese zwischen 2 oder n Benutzern stattfindet.

Also, wen haben wir da im Boot?*die Unterhaltung *die Teilnehmer *die Nachrichten

Die Nachricht wird von einem Teilnehmer erstellt und an die Unterhaltung geschickt. Der Server weiß, ob der Absender Teilnehmer der Unterhaltung ist (oder eben nicht) und fügt die Nachricht der Unterhaltung hinzu (oder eben nicht).

Vom Grundprinzip her also relativ simpel ohne viel Tamtam.

T
2.224 Beiträge seit 2008
vor 6 Jahren

@Sir Rufo
Kann sein, dass ich hier wirklich einen zugroßen Aufsatz geplant hatte.
Gerade mit der Sicht auf komplette Offline Funktion, würde dies nicht mehr klappen.
Wenn der Server nicht erreichbar ist, könnte man keine Session starten und nicht kommunizieren.
Gerade das wäre schon der Genickbruch.

Der Gedanke war dabei folgender.
1.Benutzer wählt Ansprechpartner aus
2.Client sendet dem Server die Informationen über den gewünschten Empfänger -> ID + IstGruppe Flag
3.Server legt Session an und merkt sich die Teilnehmer.
4.Server sendet die Session Guid an Client
5.Client kann dann Nachrichten mit der Guid an den Server senden

War leider nicht ganz zu Ende gedacht, da ich immer eine Session bräuchte um Nachrichten zu senden.

Ich habe mir nochmal die bisher geposteten Code Snippets angeschaut.
Ich denke hier hat MrSparkle recht.
Man sollte den ganzen Code einmal entschlacken und auch einige Teile sogar neuschreiben.
Bei den Snippets sehe ich z.B. neben der Trennung der Benutzer/Gruppen auch eine Anpassung bei den Commands.

Bsp. diese Zeile


else if(nachricht.cmd.Equals(CMD.AddNachricht))

Spricht hier was dagegen die Commands als Enum zu definieren?
Dann kannst man mit einem switch auf nachricht.cmd und dem Aufruf einer entsprechenden Methode im jeweiligen Case diesen Code Block sauber auftrennen und später auch besser warten und erweitern.
Je nach vorhandenen Befehlen bei der Nachricht, wäre da jetzt schon ein Monster von if/else if/else Verzweigung, was zukünftige Code Anpassungen nicht einfacher gestalten dürfte.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.