简体   繁体   中英

C# Trigger EventHandler with parameters

Hello i want to add a feature to my app but i just can't figure out. i want to pass some arguments or at least 1 argument to EventHandler using subscriber.

That argument will allow me to do some check and then trigger event based on that argument.

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

This is a simplified version of what i want to do so i try to make it simple so you can deal with it without garbadge stuff.

I already made a search but all i can find is the parameters is visible only in the client in the Methode handler not transmitted to the EventHandler, i think t should be stored somewhere that he can fetch for them.

Thanks in advance.

Update:

Thanks for the clarification. I think you don't fully understand how the event subscription mechanism works. Let me explain this on example. I refactored your code a little bit:

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

The two main classes here are GameAPI and Client .

GameAPI class:

  1. Keeps track of all added players in the private players list.
  2. Provides an AddPlayer method allowing clients to add players.
  3. Provides a PlayerAdded event to notify clients that a player has been added.

Client class:

  1. Subscribes to the PlayerAdded event exposed by the GameAPI .
  2. Calls AddPlayer method to add the new player.

AddPlayer method adds the player to the internal players list and calls OnPlayerAdded which notifies all subscribed clients about the new player. This notification causes the Api_PlayerAdded method in all subscribed instances of the Client class to be called. The added player will be accessible as the Player property in the e argument passed to this method.


Original answer:

I don't see any issues with your code. I modified the Api_JamesAdded method to make sure it works properly, so the full code looks like this:

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

This code prints:

Name: Clark, Pseudo: Player2

If this is not what you expected, please post the expected output.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM