繁体   English   中英

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

[英]How to stop base static events/actions firing in other derived classes

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

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

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)。 做这个的最好方式是什么? 我有很多需要这种行为的类,并希望避免在可能的情况下向每个类添加任何代码。

更新:

感谢您的所有答复,它们对您有所帮助。

我选择了一个稍有不同的选项,我承认这似乎很hacky,但对于我的目的来说效果很好。 这涉及通过操作传递类型,并让处理程序进行过滤并调用相关操作。

实体类别:

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
{
    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 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 event Action Saved;

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM