C# 计算来自单独类的发布服务器的订阅服务器数?如何从不同的类获取对处理程序调用列表的引用?

C# 计算来自单独类的发布服务器的订阅服务器数?如何从不同的类获取对处理程序调用列表的引用?,c#,events,C#,Events,我有一个C#项目,有很多活动。因此,有许多发布者和订阅者订阅了该事件。我想要的是记录每个出版商的订户数量 为了简单起见,我在这里创建了一个基本场景。在本例中,我想计算EventsCenter类中每个发布服务器的订阅者数量。我这里有几个问题 是否需要知道项目中有多少个事件,或者我必须在EventsCenter类中手动列出它们 如何在每个事件中获取对处理程序的引用 有没有办法更有效地做到这一点 在这里,我可以使用InvocationList,但不能从其他类引用处理程序。e、 g.Publisher.

我有一个C#项目,有很多活动。因此,有许多发布者和订阅者订阅了该事件。我想要的是记录每个出版商的订户数量

为了简单起见,我在这里创建了一个基本场景。在本例中,我想计算EventsCenter类中每个发布服务器的订阅者数量。我这里有几个问题

  • 是否需要知道项目中有多少个事件,或者我必须在EventsCenter类中手动列出它们
  • 如何在每个事件中获取对处理程序的引用
  • 有没有办法更有效地做到这一点
  • 在这里,我可以使用InvocationList,但不能从其他类引用处理程序。e、 g.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");
                }
            }
        }
    

    您可以声明类型为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);
                }
            }
        }
    
    
    }
    

    我无法在另一个类中使用Publisher.Foo的可能副本。我只能使用订阅和取消订阅,即(+=和-+)为什么不将
    SubscriberCount
    属性添加到
    Publisher
    类中,在该类中可以使用
    GetInvocationList()
    ?然后我必须拥有Publisher实例或使SubscriberCount保持静态。在任何一种情况下,它都不会使发布服务器保持活动状态,而这反过来又会使订阅服务器保持活动状态并造成内存问题。