繁体   English   中英

如何在 C# 中表示任何事件和任何 function?

[英]How to represent any event and any function in C#?

我有开发一个 class 以安全的方式管理事件取消订阅的想法,因此我不必在时间到来时手动写入-=到该系统的每个事件订阅(在这个系统中有订阅的事件组并一起退订)。

我想创建一个 class 来管理Dictionary ,其中是事件(任何可能的事件),是方法(任何可能的方法)。 这样,我将有一种方法可以将 function 订阅到一个事件中,并且它会在Dictionary中注册该对的同时做到这一点; 以及取消订阅使用此 class 添加的所有事件的另一种方法(它只会迭代字典并取消订阅所有事件)。

问题是:我找不到任何事件的通用类型,我可以将其用作字典键的通用参数,而且我不知道如何在 C# 中表示任何 function 以设置为字典的值。 在 C/C++ 中,我可以将它们都视为 void 指针,因为我需要的只是 function 本身的指针。

使用 C# 甚至可以做到吗? 是否有更好的方法/策略来实现这一目标?

您必须想出一种为事件生成密钥的方法,因为您不能将普通event用作字典键。 一种方法是将事件的声明 class 名称与事件名称连接起来。

然后,您可以使用字典,将其用作键,并将List<Action>作为值。 在这里, Action将是一个委托,您可以调用它来取消订阅。

您可以将该字典包装在 class 中,以提供Subscribe()Unsubscribe()方法,如下所示:

using System;
using System.Collections.Generic;

namespace ConsoleApp2
{
    class Program
    {
        static void Main()
        {
            string eventKey = test.GetType().FullName + '.' + nameof(test.MyEvent);
            subs.Subscribe(eventKey, () => test.MyEvent += handler, () => test.MyEvent -= handler);
            subs.Subscribe(eventKey, () => test.MyEvent += handler, () => test.MyEvent -= handler);
            test.RaiseEvent(); // Two handlers called.
            subs.Unsubscribe(eventKey);
            test.RaiseEvent(); // No handlers called (both were unsubscribed).
        }

        static void handler(object sender, EventArgs args)
        {
            Console.WriteLine("Handling event.");
        }

        static readonly Test test = new Test();

        static readonly EventSubscriptions subs = new EventSubscriptions();

    }

    public class EventSubscriptions
    {
        public void Subscribe(string key, Action subscribe, Action unsubscribe)
        {
            subscriptions.TryGetValue(key, out var subs);

            if (subs == null)
            {
                subs = new List<Action>();
                subscriptions.Add(key, subs);
            }

            subscribe();
            subs.Add(unsubscribe);
        }

        public void Unsubscribe(string key)
        {
            subscriptions.TryGetValue(key, out var subs);

            if (subs != null)
            {
                foreach (var unsub in subs)
                {
                    unsub();
                }

                subscriptions.Remove(key);
            }
        }

        readonly Dictionary<string, List<Action>> subscriptions = new Dictionary<string, List<Action>>();
    }

    class Test
    {
        public event EventHandler<EventArgs> MyEvent;

        public void RaiseEvent()
        {
            MyEvent?.Invoke(this, EventArgs.Empty);
        }
    }
}

假设您所有的事件处理程序都是void MyHandler(object sender, EventArgs e)种类,您的字典将是Dictionary<string, Action<object,EventArgs>> (假设您希望键是字符串 - 其他任何东西也可以)

暂无
暂无

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

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