Reputation: 381
I am using an external class to open up a connection to a remote application. This class receives the data from the remote application which is handled via a handler.
To this handler I have added several checks to parse the data in separate methods. However I am now stuck at the point where I need to access the object again which triggered the event to call a method on it. I am sure this is a pretty basic question but I am just starting with OOP.
public static void Main(string[] args) {
IBattleNET b = new BattlEyeClient(loginCredentials);
b.MessageReceivedEvent += HandleMessage;
b.Connect();
}
private static void HandleMessage(BattlEyeMessageEventArgs args) {
//call a method to analyze data parse
PlayerList(args.Message);
}
private static void parsePlayerList(string playerList) {
// At this point I need to access the object b again to to call a method
}
Upvotes: 2
Views: 5348
Reputation: 44971
Since your incoming method is static, you are presented with some challenges, particularly what happens when multiple messages arrive in a very close period of time? If you store the information that you want to reuse later, it could easily be overwritten by the next message that is received.
In cases like this, I generally create a new class that is responsible for the parsing and processing of the incoming message and, in the event handler, create a new instance of that class passing the event arguments to the constructor.
From that point forward, all processing of the message occurs in the class instance.
For example, you could have a class like this that stores the message, validates it, and then later performs some parsing on it::
public class PlayerListEvent
{
private string m_sMessage;
public PlayerListEvent(String sMessage)
{
m_sMessage = sMessage;
}
public Boolean MessageIsValid()
{
// Validate the incoming message
return true;
}
public void ParseMessage() {
// Perform the message parsing
}
}
You could store all incoming messages in a list (or class or some other storage mechanism) so that they can be processed as needed:
private static System.Collections.Generic.List<PlayerListEvent> m_cReceivedMessages = new System.Collections.Generic.List<PlayerListEvent>();
Then, when your message arrives, you can create a new instance of the class and, if it's valid, add it to the queue for processing later (you could do just about anything here including firing a background worker process to handle the incoming message, etc):
private static void HandleMessage(BattlEyeMessageEventArgs args) {
//call a method to analyze data parse
var oPlayerListEvent = new PlayerListEvent(args.Message);
if (oPlayerListEvent.MessageIsValid()) {
lock (m_cReceivedMessages) {
m_cReceivedMessages.Add(oPlayerListEvent);
}
}
}
Upvotes: 1
Reputation: 26
Modify the handler to pass over the object:
b.MessageRecievedEvent += (e) => HandleMessage(b, e);
....
private static void HandleMessage(IBattleNet b, BattleMessageEventArgs args) {
....
The lambda expression stores the args as 'e', then calls HandleMessage by passing it both the object and 'e'.
The convention Pickles presented is better practice, however, if you have access to and can change the event itself inside of IBattleNET.
Upvotes: 1
Reputation: 8503
Typically events use delegates that have two parameters in their signature. An object "source" parameter to represent the sender and an "args" parameter to represent the event args.
If you have access to the MessageReceivedEvent
you should change the delegate to include an "object" parameter to represent the sender. Then your HandleMessage
method would look like this:
private static void HandleMessage(object sender, BatlEyeMessageEventArgs args)
{
var battleNet = sender as IBattleNet;
if (battleNet == null)
return;
battleNet.Foo();
PlayerList(args.Message);
}
Upvotes: 1