繁体   English   中英

将额外参数传递给事件处理程序?

[英]Pass extra parameters to an event handler?

假设我想在分配事件处理程序时传递一些额外的数据。 考虑以下代码:

private void setup(string someData)
{
     Object.assignHandler(evHandler);
}

public void evHandler(Object sender)
{
    // need someData here!!!
}

我将如何将someData放入我的evHandler方法中?

private void setup(string someData)
{
     Object.assignHandler((sender) => evHandler(sender,someData));
}
public void evHandler(Object sender, string someData)
{
    // need someData here!!!
}

我很难弄清楚上面Object.assignHandler((sender) => evHandler(sender,someData));的例子,尤其是: Object.assignHandler((sender) => evHandler(sender,someData)); 因为没有字面意义上的Object.assignHandler这样的东西。 所以我做了更多的谷歌搜索并找到了这个例子 Peter Duniho 的回答让我印象深刻(这不是我的作品):

剪断

通常的方法是将匿名方法与具有您修改过的签名的事件处理程序一起使用。 例如:

 void Onbutton_click(object sender, EventArgs e, int i) { ... } button.Click += delegate(object sender, EventArgs e) { Onbutton_click(sender, e, 172); };

当然,您不必传入 172,甚至不必将第三个参数设为 int。 :)

/剪断

使用该示例,我能够使用 lambda 表示法将两个自定义ComboBoxItem对象传递给Timer.Elapsed事件:

simulatorTimer.Elapsed +=
(sender, e) => onTimedEvent(sender, e,
(ComboBoxItem) cbPressureSetting.SelectedItem,
(ComboBoxItem) cbTemperatureSetting.SelectedItem);

然后进入它的处理程序:

static void onTimedEvent(object sender, EventArgs e, ComboBoxItem pressure, ComboBoxItem temperature)
    {
        Console.WriteLine("Requested pressure: {0} PSIA\nRequested temperature: {1}° C", pressure, temperature);
    }

这不是以上示例中的任何新代码,但它确实演示了如何解释它们。 希望像我这样的人发现它有启发性和有用性,这样他们就不会像我一样花费数小时试图理解这个概念。

这段代码适用于我的项目(除了我认为不会改变示例工作方式的ComboBoxItem对象的非线程安全异常)。 我现在正在弄清楚。

捕获的变量:

private void setup(string someData)
{
    Object.assignHandler((sender,args) => {
        evHandler(sender, someData);
    });
}

public void evHandler(Object sender, string someData)
{
    // use someData here
}

或(C# 2.0 替代方案):

    Object.assignHandler((EventHandler)delegate(object sender,EventArgs args) {
        evHandler(sender, someData);
    });

你可以尝试这样做:

string yourObject;

theClassWithTheEvent.myEvent += (sender, model) =>
{
 yourObject = "somthing";
}

我的类似问题被标记为重复,所以我想我会在这里添加一个答案,因为它不会让我回答我的问题。

class Program
    {
        delegate void ComponentEventHandler(params dynamic[] args);

        event ComponentEventHandler onTest;

        static void Main(string[] args)
        {  
            Program prg = new Program();

            // can be bound to event and called that way
            prg.onTest += prg.Test;
            prg.onTest.Invoke("What", 5, 12.0);

            Console.ReadKey();
        }

        public void Test(params dynamic[] values)
        {
            // assign our params to variables
            string name = values[0];
            int age = values[1];
            double value = values[2];

            Console.WriteLine(name);
            Console.WriteLine(age);
            Console.WriteLine(value);
        }
    }

您可以创建一个具有基于 Object 的附加属性的自定义对象:

class CustomObject : Object
{
    public string SomeData;
}

private void setup(string someData)
{
    CustomObject customObject = new CustomObject { SomeData = someData };
    CustomObject.assignHandler(evHandler);
}

public void evHandler(Object sender)
{
    string someData = ((CustomObject)sender).SomeData;
}

例如,如果数据在初始化后不应再更改,您还可以添加自定义构造函数。

这是我将额外参数传递给计时器处理程序的单行解决方案。

private void OnFailed(uint errorCode, string message)
{
    ThreadPoolTimer.CreateTimer((timer) => {
    UI.ErrorMessage = string.Format("Error: 0x{0:X} {1}", errorCode, message);
    }, System.TimeSpan.FromMilliseconds(100));
}

好吧,使someData成为成员变量的最简单方法 id 如下所示:

public class MyClass
{
    private string _eventData;

    private void setup(string someData) 
    {
       _eventData = someData;
       Object.assignHandler(evHandler);
    }

    public void evHandler()
    {
        // do something with _eventData here
    }
}

我不确定这是最好的方法,但这确实取决于事件类型、对象等。

我的解决方案涉及使用调用 lambda function 的操作订阅我的事件,该操作为我的事件处理程序提供事件参数和我的额外参数。 然后我将此动作存储在字典中。 当我想取消订阅时,我可以使用存储的操作来取消订阅。

这很有效,我在取消订阅之前和之后阅读了听众的长度,它确实减少了。

    public class Player
    {
        public Action<JumpInfo> OnJump;
    }

    public class PlayerJumpListener
    {
        public List<Player> MyPlayerList;
        private Dictionary<Player, Action<JumpInfo>> _jumpActionsByPlayer = new Dictionary<Player, Action<JumpInfo>>();

        private void Subscribe()
        {
            foreach (Player player in MyPlayerList)
            {
                Action<JumpInfo> playerJumpAction = (jumpInfo) => HandlePlayerJump(jumpInfo, player);
                player.OnJump += playerJumpAction;

                _jumpActionsByPlayer.Add(player, playerJumpAction);
            }
        }

        private void Unsubscibe()
        {
            foreach (KeyValuePair<Player, Action<JumpInfo>> kvp in _jumpActionsByPlayer)
            {
                kvp.Key.OnJump -= kvp.Value;
            }
        }

        private void HandlePlayerJump(JumpInfo jumpInfo, Player player)
        {
            // player jumped
        }
    }

在一位同事好心帮助我之前,我在网上搜索了一下,天哪,我觉得自己很蠢。 Brackets 是EventHandler的解决方案。

前任。

event EventHandler<(int, bool)> EventName;

然后拿起它:

private void Delegate_EventName(object sender, (int, bool) e)

然后您可以访问信息:

var temp = e.Item1;<br>
var temp2 = e.Item2;<br>

或者您可以按预期为参数添加名称并通过e调用它们:

private void Delegate_EventName(object sender, (int num, bool val) e)

然后您可以访问信息:

var temp = e.num;
var temp2 = e.val;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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