【问题标题】:C# Trigger EventHandler with parametersC# 带参数触发 EventHandler
【发布时间】:2020-05-17 05:00:24
【问题描述】:

您好,我想向我的应用程序添加一项功能,但我就是想不通。 我想使用订阅者将一些参数或至少 1 个参数传递给 EventHandler。

该参数将允许我进行一些检查,然后根据该参数触发事件。

public class Client
{
    public Client()
    {
        GameAPI api = new GameAPI();
        api.AddedPlayerEvent += Api_ClarkAdded;
        api.Do();
    }

    private void Api_ClarkAdded(object sender, GameAPI.AddedPlayerEvents e)
    {
        Console.WriteLine("User Clark found");
    }
}


public class GameAPI
{
    public event EventHandler<AddedPlayerEvents> AddedPlayerEvent;
    List<AddedPlayerEvents> AddedPlayers = new List<AddedPlayerEvents>();
    public GameAPI()
    {
        // some code to simulate generating some data
        AddedPlayers.Add(new AddedPlayerEvents("Player1","James"));
        AddedPlayers.Add(new AddedPlayerEvents("Player2", "Clark"));
        AddedPlayers.Add(new AddedPlayerEvents("Player3", "Steve"));
    }

    public void Do()
    {
        // simulating code ...
        //trigger event
        if (AddedPlayers.Any(f => f.Name == "Clark")) /*value Clark should come from client using subsciber or something else*/
        {
            OnPlayerAdded(AddedPlayers.First(f => f.Name == "Clark"));
        }
    }

    protected virtual void OnPlayerAdded(AddedPlayerEvents e)
    {
        EventHandler<AddedPlayerEvents> handler = AddedPlayerEvent;
        if (handler != null)
        {
            handler(this, e);
        }
    }

    public class AddedPlayerEvents
    {
        public string Pseudo { get; set; }
        public string Name { get; set; }
        public AddedPlayerEvents(string pseudo, string name)
        {
            Pseudo = pseudo;
            Name = name;
        }
    }
}

这是我想做的一个简化版本,所以我尽量让它简单,这样你就可以在没有垃圾的情况下处理它。

我已经进行了搜索,但我能找到的只是参数仅在 Methode 处理程序中的客户端中可见,而不是传输到 EventHandler,我认为应该将它们存储在他可以为它们获取的地方。

提前致谢。

【问题讨论】:

  • 我不清楚这个问题。我看到至少 3 种不同的方式来解释您的既定目标:1)您希望为每个添加的玩家引发事件,并希望事件处理程序仅针对特定的硬编码事件触发; 2)你想要每个玩家的事件,但想要重用一个通用的事件处理程序,可以传递玩家的名字来触发;或 3) 你想将玩家的名字传递给 Do() 方法,并让它只为所需的玩家引发事件。第三个最接近您现在拥有的代码,但就事件的通常使用方式而言,它是最不传统的。
  • 请编辑您的问题,以便清楚您真正希望代码做什么。确保您描述了代码现在的功能与您想要的有何不同、您为使其执行您想要的功能所做的尝试以及您需要帮助的具体。另请阅读How to Ask,了解如何以清晰、可回答的方式提出您的问题。
  • 为什么不能将值“Clark”从类 Client 传递给方法“Do”?这就是你要找的吗?
  • 好吧,我不想在Do方法上传递参数,希望有另一种方法可以直接处理EventHandler订阅者但似乎不存在

标签: c# eventhandler


【解决方案1】:

更新:

感谢您的澄清。我想你还没有完全理解事件订阅机制是如何工作的。让我举例说明一下。我稍微重构了你的代码:

using System;
using System.Collections.Generic;

class Program
{
    static void Main(string[] args)
    {
        Client client = new Client();
    }
}

public class Client
{
    public Client()
    {
        GameAPI api = new GameAPI();
        api.PlayerAdded += Api_PlayerAdded;
        api.AddPlayer(new Player("Player2", "Clark"));
    }

    private void Api_PlayerAdded(object sender, PlayerAddedEventArgs e)
    {
        Console.WriteLine($"API PlayerAdded event has triggered. Arguments: e.Player.Name = {e.Player.Name}, e.Player.Pseudo = {e.Player.Pseudo}");
    }
}

public class PlayerAddedEventArgs: EventArgs
{
    public PlayerAddedEventArgs(Player player)
    {
        Player = player;
    }

    public Player Player { get; }
}

public class Player
{
    public Player(string pseudo, string name)
    {
        Pseudo = pseudo;
        Name = name;
    }

    public string Pseudo { get; }
    public string Name { get; }
}

public class GameAPI
{
    private List<Player> players = new List<Player>();

    public event EventHandler<PlayerAddedEventArgs> PlayerAdded;

    public void AddPlayer(Player player)
    {
        players.Add(player);
        OnPlayerAdded(new PlayerAddedEventArgs(player));
    }

    protected virtual void OnPlayerAdded(PlayerAddedEventArgs e)
    {
        PlayerAdded?.Invoke(this, e);
    }
}

这里的两个主要类是GameAPIClient

GameAPI类:

  1. 在私人players 列表中跟踪所有添加的玩家。
  2. 提供AddPlayer 方法允许客户端添加玩家。
  3. 提供PlayerAdded 事件以通知客户端已添加玩家。

Client类:

  1. 订阅PlayerAdded 暴露的GameAPI 事件。
  2. 调用AddPlayer方法添加新播放器。

AddPlayer 方法将播放器添加到内部players 列表并调用OnPlayerAdded 通知所有订阅的客户端有关新播放器的信息。此通知导致调用Client 类的所有订阅实例中的Api_PlayerAdded 方法。添加的播放器将可作为传递给此方法的e 参数中的Player 属性访问。


原答案:

我没有发现您的代码有任何问题。我修改了Api_JamesAdded 方法以确保它正常工作,所以完整代码如下所示:

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        Client client = new Client();
    }
}

public class Client
{
    public Client()
    {
        GameAPI api = new GameAPI();
        api.AddedPlayerEvent += Api_JamesAdded;
        api.Do();
    }

    private void Api_JamesAdded(object sender, GameAPI.AddedPlayerEvents e)
    {
        Console.WriteLine($"Name: {e.Name}, Pseudo: {e.Pseudo}");
    }
}

public class GameAPI
{
    public event EventHandler<AddedPlayerEvents> AddedPlayerEvent;
    List<AddedPlayerEvents> AddedPlayers = new List<AddedPlayerEvents>();
    public GameAPI()
    {
        // some code to simulate generating some data
        AddedPlayers.Add(new AddedPlayerEvents("Player1", "James"));
        OnPlayerAdded(AddedPlayers.First(f => f.Pseudo == "Player1"));

        AddedPlayers.Add(new AddedPlayerEvents("Player2", "Clark"));
        OnPlayerAdded(AddedPlayers.First(f => f.Pseudo == "Player2"));

        AddedPlayers.Add(new AddedPlayerEvents("Player3", "Steve"));
        OnPlayerAdded(AddedPlayers.First(f => f.Pseudo == "Player3"));
    }

    public void Do()
    {
        // simulating code ...
        //trigger event
        if (AddedPlayers.Any(f => f.Name == "Clark")) /*value Clark should come from client using subsciber or something else*/
        {
            OnPlayerAdded(AddedPlayers.First(f => f.Name == "Clark"));
        }
    }

    protected virtual void OnPlayerAdded(AddedPlayerEvents e)
    {
        EventHandler<AddedPlayerEvents> handler = AddedPlayerEvent;
        if (handler != null)
        {
            handler(this, e);
        }
    }

    public class AddedPlayerEvents
    {
        public string Pseudo { get; set; }
        public string Name { get; set; }
        public AddedPlayerEvents(string pseudo, string name)
        {
            Pseudo = pseudo;
            Name = name;
        }
    }
}

此代码打印:

Name: Clark, Pseudo: Player2

如果这不是您所期望的,请发布预期的输出。

【讨论】:

  • 代码工作正常,因为我硬编码了应该作为变量出现的值“Clark”。
猜你喜欢
  • 1970-01-01
  • 2019-09-11
  • 2013-09-07
  • 1970-01-01
  • 2011-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-28
相关资源
最近更新 更多