如何停止在其他派生类中触发的基本静态事件/操作

本文关键字:静态 事件 操作 何停止 其他 派生 | 更新日期: 2023-09-27 18:33:26

我正在使用WinForms选项卡式MDI界面在C#中开发LOB应用程序。我有各种带有 DataGridView 的表单,允许用户选择他们感兴趣的对象,然后他们可以在新表单中查看/编辑该对象。

我的每个主要业务对象都继承自实体,定义如下:

public abstract class Entity
{
    public static event Action Saved;
    internal virtual void OnSaved()
    {
        if (Saved != null)
        {
            Saved();
        }
    }
}

然后,我有了填充网格的对象(这些实际上是从 Linq-to-SQL 自动生成的类,尽管我可以用普通类复制问题(:

class Class1 : Entity
{
    //Stuff
}

class Class2 : Entity
{
    //Stuff
}

我想知道何时修改给定类的对象,但我不在乎哪个实例(因此是静态操作(,以便我可以刷新网格并执行其他活动。

当事件从派生类实例触发时,问题就出现了 - 它也会为所有其他派生类触发。例如:

Class1.Saved += new Action(s1);
Class2.Saved += new Action(s2);
private void TestIt()
{
    Class2 o2 = new Class2();
    o2.OnSaved();  
}

这将触发 s1 和 s2,但我只想触发特定的一个(即 s2(。最好的方法是什么?我有很多类需要这种行为,并且希望尽可能避免向每个类添加任何代码。

更新:

感谢您的所有回复,他们非常有帮助。

选择了一个稍微不同的选项,我承认这似乎很笨拙,但非常适合我的目的。这涉及随操作一起传递类型,并让处理程序筛选和调用相关操作。

实体类:

public abstract class Entity
{
    public static event Action<Type> Saved;

    internal void OnSaved()
    {
        private Action<Type> SavedCopy = Saved;        
        if (SavedCopy != null)
            SavedCopy(this.GetType());
    }
}

挂接处理程序:

 Entity.Saved += new Action<Type>(Handler);

示例处理程序方法(这将因表单而异(:

    void Handler(Type obj)
    {
       if (obj==typeof(Class1))
           UpdateGrid();
       else if (obj==typeof(Class2))
           UpdateBasicInfo();
       else if (obj == typeof(Class3))
           DoAnotherThing();
    }

如何停止在其他派生类中触发的基本静态事件/操作

使用泛型可能是一种解决方法;每个泛型类都会获得静态字段的副本。

public abstract class Entity<T>
{
    public static event Action Saved = delegate { };
    internal virtual void OnSaved()
    {
        Saved();
    }
}
class Class1 : Entity<Class1>
{
    //Stuff
}
class Class2 : Entity<Class2>
{
    //Stuff
}

我不确定这样做是个好主意,但是您可以在订阅和保存数据时指定类型:

public abstract class Entity
{
    private static Dictionary<Type, Action> Subscribers
         = new Dictionary<Type, Action>();
    internal virtual void OnSaved()
    {
        OnSaved(GetType());
    }
    private OnSaved(Type type)
    {
        Action subscribed;
        Subscribers.TryGetValue(type, out subscribed);
        if (subscribed != null)
            subscribed();
    }
    public Subscribe(Type type, Action action)
    {
        Action subscribed;
        Subscribers.TryGetValue(type, out subscribed);
        Subscribers[type] = subscribed + action;
    }
    public Unsubscribe(Type type, Action action)
    {
        Action subscribed;
        Subscribers.TryGetValue(type, out subscribed);
        Subscribers[type] = subscribed - action;
    }
}

请记住,此代码不是线程安全的,因此如果要同时从不同的线程使用它,则需要添加锁定。

每种类型都需要一个事件,因为在基类型上定义事件时,无法确定委托注册为哪种类型。

public abstract class Entity
{
    internal abstract void OnSaved();
}
class Class1 : Entity
{
    public static event Action Saved = () => { };
    internal override void OnSaved()
    {
        this.Saved();
    }
    //Stuff
}
class Class2 : Entity
{
    public static event Action Saved = () => { };
    internal override void OnSaved()
    {
        this.Saved();
    }
    //Stuff
}

为什么它必须是静态的? 改为将其设置为实例事件。

public event Action Saved;

您必须为每个实例挂接它,而不是每个类只挂接一次(或者在当前情况下,一次(,但它会将事件分开。