从事件处理程序访问对象

时间:2012-08-12 00:00:51

标签: c# event-handling

我正在使用外部类来打开与远程应用程序的连接。此类接收来自远程应用程序的数据,该数据通过处理程序处理。

对于这个处理程序,我添加了几个检查来分析单独的方法中的数据。但是我现在停留在需要再次访问对象的位置,触发事件以调用它上面的方法。我确信这是一个非常基本的问题,但我只是从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
}

3 个答案:

答案 0 :(得分:1)

通常,事件使用在其签名中具有两个参数的委托。用于表示发送方的对象“source”参数和用于表示事件args的“args”参数。

如果您有权访问MessageReceivedEvent,则应更改委托以包含“object”参数来表示发件人。那么您的HandleMessage方法将如下所示:

private static void HandleMessage(object sender, BatlEyeMessageEventArgs args)
{
        var battleNet = sender as IBattleNet;
        if (battleNet == null)
           return;

        battleNet.Foo();
        PlayerList(args.Message);
}

答案 1 :(得分:1)

由于您的传入方法是静态的,因此您会遇到一些挑战,特别是当多个消息在非常接近的时间内到达时会发生什么?如果您存储了稍后要重用的信息,则可能很容易被接收到的下一条消息覆盖。

在这种情况下,我通常会创建一个新类,负责解析和处理传入消息,并在事件处理程序中创建该类的新实例,将事件参数传递给构造函数。

从那时起,消息的所有处理都发生在类实例中。

例如,你可以有一个这样的类来存储消息,验证它,然后再对它进行一些解析::

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
    }
}

您可以将所有传入的消息存储在列表(或类或其他存储机制)中,以便可以根据需要对它们进行处理:

    private static System.Collections.Generic.List<PlayerListEvent> m_cReceivedMessages = new System.Collections.Generic.List<PlayerListEvent>();

然后,当您的消息到达时,您可以创建该类的新实例,如果它有效,则将其添加到队列中以便稍后处理(您可以在此处执行任何操作,包括触发后台工作进程来处理传入消息等):

    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);
            }
        }
    }

答案 2 :(得分:1)

修改处理程序以传递对象:

b.MessageRecievedEvent += (e) => HandleMessage(b, e);
....
private static void HandleMessage(IBattleNet b, BattleMessageEventArgs args) {
....

lambda表达式将args存储为'e',然后通过传递对象和'e'来调用HandleMessage。

如果您有权访问并可以在IBattleNET内部更改事件本身,那么提出的Pickles会议就是更好的做法。