// This becomes has the same signature as the MessageReceivedHandler delegate and so can // be attached; hooked; follow; subscribe to the server event. // Since nothing other than the types in the assembly should use this handler, we make it internal. internal void RelayMessage(int sender, NewMessageEventArgs e) { // The sender is this instance, we don't need to care about the message or event if (sender == id) { return; } // Since we are just sending a message like normal, we can just use the method that // is used to send the messages normally. SendMessage(e.Message.Value); }
// Through this method, we can fire the event in a thread safe manor from everywhere inside the class. private void IncommingMessage(NewMessageEventArgs e) { lock (messageReceivedEventPadlock) { // When the server is notified it will raise its own event with the same message and id. MessageReceivedEvent?.Invoke(id, e); // ?. is called a null conditional operator. // If the target (here, messageReceivedEvent) is null, it returns null // Otherwise it calls the specified member. // In normal syntax this is (explicitely): // MessageReceivedHandler handler = messageReceivedEvent; // if (handler == null) return null; // else return messageReceivedEvent.Invoke(id, new NewMessageEventArgs(message)); // For this case it would be: // MessageReceivedHandler handler = messageReceivedEvent; // if (handler != null) messageReceivedEvent.Invoke(id, new NewMessageEventArgs(message)); // as returns from operators are ignored the value is not assigned to anything. } }