从单独的类中计算发布者的订阅者数量?如何从不同的类中引用Handler的InvocationList?

时间:2015-10-26 19:40:52

标签: c# events

我有一个C#项目,其中有很多事件。因此,有许多发布者和许多订阅者订阅该活动。我想要的是保持每个发布者的订阅者数量。

为简单起见,我在这里创建了一个基本场景。在此示例中,我想计算Class EventsCounter中每个发布者的订阅者数量。我在这里有很多问题。

  1. 无论如何都知道项目中有多少个事件,或者我必须在Class EventsCounter中手动列出它们?
  2. 如何在每个事件中引用处理程序?
  3. 有没有办法更有效地做到这一点?
  4. 在这里,我可以使用InvocationList,但我无法从其他类引用处理程序。例如Publisher.Foo给了我一个错误。

        using System;
    
        namespace EventTest
        {
            class Program
            {
                static void Main(string[] args)
                {
                    GenerateEvents ge = new GenerateEvents();
                }
            }
    
            public class EventsCounter
            {
                //need to count all events and corresponding subscribers here
            }
    
            public class GenerateEvents
            {
                public GenerateEvents()
                {
                    Publisher publisher = new Publisher();
                    Subscriber subscriber1 = new Subscriber();
                    Subscriber subscriber2 = new Subscriber();
    
                    publisher.Foo += subscriber1.FooHandler;
                    publisher.Foo += subscriber2.FooHandler;
                    publisher.RaiseFoo();
    
                    publisher.Foo -= subscriber1.FooHandler;
                    publisher.Foo -= subscriber2.FooHandler;
                    publisher.RaiseFoo();
    
                    Console.Read();
                }
            }
    
            public class Publisher
            {
                public event EventHandler Foo;
                int count = 0;
    
                public void RaiseFoo()
                {
                    Console.WriteLine("Raising Foo");
                    EventHandler handler = Foo;
    
                    if (handler != null)
                    {
                        foreach (EventHandler subscriber in handler.GetInvocationList())
                        {
                            count++;
                            subscriber(this, EventArgs.Empty);
                        }
                        Console.WriteLine("The count is {0}", count);
                    }
                    else
                    {
                        Console.WriteLine("No subscribers!");
                    }
                }
            }
    
            public class Subscriber
            {
                public void FooHandler(object sender, EventArgs e)
                {
                    Console.WriteLine("Subscriber Called");
                }
            }
        }
    

1 个答案:

答案 0 :(得分:1)

您可以声明Event类型的属性。这样,您就可以跟踪订阅和删除活动 此外,您可以通过调用事件的GetInvocationList()方法来枚举订阅的处理程序。我在发布商的EnumerateSubscribers()方法中证明了这一点 下面的代码是一个演示:

using System;

namespace MyApp
{
    class Program
    {
        static void Main(string[] args)
        {
            var p = new Publisher();
            var s1 = new Subscriber("first");
            s1.Subscribe(p);
            p.RaiseFoo(null, null);
            var s2 = new Subscriber("second");
            s2.Subscribe(p);
            p.RaiseFoo(null, null);
            p.EnumerateSubscribers();
            s1.Unsubscribe(p);
            p.RaiseFoo(null, null);
            s2.Unsubscribe(p);
            Console.ReadKey();
        }
    }

    public class Subscriber
    {
        public string Name { get; set; }

        public Subscriber(string name)
        {
            this.Name = name;
        }

        public void Subscribe(Publisher p)
        {
            p.Foo += this.HandleFoo;
        }

        public void Unsubscribe(Publisher p)
        {
            p.Foo -= this.HandleFoo;
        }

        private void HandleFoo(object sender, EventArgs e)
        {
            Console.WriteLine(this.Name + " is called");
        }

        public override string ToString()
        {
            return this.Name;
        }
    }

    public class Publisher
    {
        private int count;
        private EventHandler _foo;

        public void RaiseFoo(object sender, EventArgs e)
        {
            if (_foo != null)
            {
                _foo(sender, e);
            }
        }

        public void EnumerateSubscribers()
        {
            if (_foo != null)
            {
                foreach (var item in _foo.GetInvocationList())
                {
                    Console.WriteLine("Subscriber object:" + item.Target?.ToString());
                }
            }
        }

        public event EventHandler Foo
        {
            add
            {
                _foo += value;
                Console.WriteLine("Count:" + ++count);
            }

            remove
            {
                _foo -= value;
                Console.WriteLine("Count:" + --count);
            }
        }
    }


}