有没有一种方法可以让静态方法访问类的所有非静态实例?

5

这可能是一个愚蠢的问题,但我还是要问一下...我正在使用C#.NET编程。我有一个包含非静态实例EventHandler的类。是否有可能从静态方法中触发该类的每个实例的EventHandler?我知道这很难!


这很令人困惑。听起来你想从类型的每个其他实例触发一个实例事件处理程序。换句话说,每个实例都会在已创建的类的每个其他实例上引发一个事件处理程序...是这样吗? - David Morton
1
观察者模式来拯救? - Rob Allen
虽然可能有可行的答案,但您可以考虑扩展问题以更详细地描述您的情境;可能会有更优雅的解决方案,例如观察者模式甚至 Rx(如果您能够使用GoLive许可证),这可能是您问题的好选择。 - Richard Anthony Freeman-Hein
4个回答

6
你可以这样做,但你需要创建一个包含所有对象的静态集合:
public class Thing
{
   public static List<Thing> _things = new List<Thing>();

   public Thing()
   {
       _things.Add(this);
   }

   public static void SomeEventHandler(object value, EventHandler e)
   {
      foreach (Thing thing in _things)
      {
           // do something.
      }
   }
}

你需要注意不要积累太多的“物品”。确保在不需要它们时从列表中删除它们。


2
虽然你可能想将它们改为弱引用,至少在终结器中删除它们,并且如果你的Things将在多个线程上创建,可以添加Remi的lock()。这在大多数库情况下是无法预先知道的。 - Pontus Gagge
1
请记住,您可以在不调用构造函数的情况下创建实例:https://dev59.com/4HVC5IYBdhLWcg3wbghT - Brian Rasmussen

5

没有,基本上找不到所有类的实例的方法,除非你自己编写代码来做这件事。

编辑:不知道为什么会被踩。总之,再补充一点细节:你应该避免需要这样做。你可以让你的类型实现 IDisposable,然后在构造函数中注册一个静态事件处理程序,在Dispose方法中取消注册。甚至可以有一个终结器来为您执行此操作,这将为您带来性能损失,但如果您未能处理实例,则至少不会泄漏。

然而,这些都是相当严峻的选项。最好的方法是尽量重新设计以避免这种要求。也许您可以给我们更多关于您所尝试做的事情的信息,我们可以想出一个解决方法?


+1 - 这是需要重新设计,而不仅仅是添加更多代码的原因。由类的实例订阅观察者而不是尝试在每个实例上调用静态事件处理程序,在有限的信息下更有意义。 - Rob Allen

1
你可以这样做:
    public class MyClass{
private static List<MyClass> Instances = new List<MyClass>();

    public MyClass(){
lock(typeof(MyClass)){
Instances.Add(this);
}

}}

在此之后,您可以随心所欲地处理实例。


2
除非你非常小心地确保删除所有的东西,否则会出现内存泄漏。 哦,由于这个字段是公共的,所以使用它的所有内容都必须小心同步 :( - Jon Skeet
我编辑以将该字段设置为私有。David想对所有实例执行某些操作,因此他必须小心处理内存泄漏问题。 - remi bourgarel

1

我可能误解了你的意思,但应该很简单...

这是主文件

using System;
using IdeaClass;

namespace TestIdeas
{
    class Program
    {
        static void Main(string[] args)
        {
            Ideas i = new Ideas();
            Ideas.triggerMany();
            Console.ReadLine();
        }
    }
}

接下来是Ideas类:

using System;

namespace IdeaClass
{
    public class Ideas
    {
        static OtherClass oc = new OtherClass();
        public static void triggerMany()
        {
            oc.runThing("textual");
        }

        public Ideas()
        {
            Ideas.oc.ThingEvent += DoThingHandler;
        }

        public void DoThingHandler(string thing)
        {
            System.Console.WriteLine(thing);
        }
    }
}

然后是另一个类。

using System;

namespace IdeaClass
{
    class OtherClass
    {
        public delegate void DoThing(string text);
        public event DoThing ThingEvent;

        public void runThing(string text)
        {
            if (ThingEvent != null)
            {
                ThingEvent(text);
            }
        }
    }
}

这确实会导致事件引发类和静态调用类之间的不必要耦合,但它似乎可以实现你想要的功能。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接