动态订阅/取消订阅活动

时间:2012-08-26 18:13:13

标签: c# event-handling subscribe unsubscribe

我正在使用C#开展纸牌游戏项目。在这个游戏中,有很多事件被解雇,桌面上的牌需要订阅。但是,我需要这些卡动态订阅和取消订阅事件,以便当前未激活的卡不会响应被触发的事件。

我的解决方案是使用EventManager父类,每个事件都有一个子级。这些管理器中的每一个都将具有订阅/取消订阅方法,这些方法将EventHandler作为参数。调用时,方法将从分配给该管理器的事件中订阅/取消订阅提供的处理程序。

以下代码是一个基本的控制台应用程序,它使用与我的纸牌游戏相同的设计模式,并且具有相同的问题。您可以将其直接粘贴到Visual Studio中,它将运行。

using System;
using System.Collections.Generic;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var example = new ExampleCard();
            example.Subscribe();
            example.Events.FireEventOne(null, new EventArgs());
            example.UnSubscribe();
            example.Events.FireEventOne(null, new EventArgs());
            Console.ReadLine();
        }
    }

    public class EventContainer
    {
        public delegate void EventOne(Object sender, EventArgs r);
        public event EventOne OnEventOne;

        public EventContainer()
        {
            OnEventOne += Default_Handler;
        }

        public void Default_Handler(object sender, EventArgs e)
        {

        }

        public void FireEventOne(object sender, EventArgs e)
        {
            OnEventOne(sender, e);
        }
    }

    public class EventManager
    {
        protected EventContainer Events;

        public EventManager(EventContainer events)
        {
            Events = events;
        }

        public virtual void Subscribe(EventHandler handler)
        {
        }

        public virtual void Unsubscribe(EventHandler handler)
        {
        }
    }

    public class EventOneManager : EventManager
    {
        public EventOneManager(EventContainer events)
            : base(events)
        {
        }

        public override void Subscribe(EventHandler handler)
        {
            Events.OnEventOne += new EventContainer.EventOne(handler);
        }

        public override void Unsubscribe(EventHandler handler)
        {
            Events.OnEventOne -= new EventContainer.EventOne(handler);
        }
    }

    public class ExampleCard
    {
        public EventContainer Events = new EventContainer();
        private readonly List<EventManager> _subscribedEvents = new List<EventManager>();

        public ExampleCard()
        {
            _subscribedEvents.Add(new EventOneManager(Events));
        }

        public void Example_OnEventOneFired(object sender, EventArgs e)
        {
            Console.WriteLine("Event One was fired.");
        }

        public void Subscribe()
        {
            _subscribedEvents[0].Subscribe(Example_OnEventOneFired);
        }

        public void UnSubscribe()
        {
            _subscribedEvents[0].Unsubscribe(Example_OnEventOneFired);
        }
    }
}

EventOneManager.Subscribe()似乎有效,但EventOneManager.Unsubscribe()没有;调用该方法后,示例卡保持订阅该事件,我无法弄清楚原因,或如何解决它。

我试过的一件事就是删除'new EventContainer.EventOne'调用,使它看起来像这样:

public override void Unsubscribe(EventHandler handler)
            {
                Events.OnEventOne -= handler;
            }

但是我得到了这个错误:无法将类型'System.EventHandler'隐式转换为'ConsoleApplication1.EventContainer.EventOne“有什么建议吗?

此外,我希望能够使用自定义的EventArgs类,但我无法弄清楚如何传入一个通用的处理程序,它将适用于我正在使用的任何事件。我可以解决这个问题,但我更喜欢使用自定义EventArgs。

1 个答案:

答案 0 :(得分:1)

您需要将事件更改为EventHandler类型 你不应该自己制作代表类型。

要传递其他数据,请使用EventHandler<T>