在事件上执行错误的派生类方法?

时间:2011-11-17 08:38:59

标签: c# events inheritance custom-event

public Class A
{

   public A()
   {
     someotherclass.someevent += new EventHandler(HandleEvent);
   }

   private void HandleEvent(object sender,CustomEventArgs e) 
   {
      if(e.Name == "Type1")
           Method1();
      else if(e.Name == "Type2")
           Method2();
   }

   protected virtual void Method1(){}
   protected virtual void Method2(){}
}

public class B: A
{
   public B()
   { /*Something*/}

   protected override void Method1(){/*some logic*/}
   protected override void Method2(){/*some other logic*/}
}

public class C: A
{
   public C()
   { /*Something*/}

   protected override void Method1(){/*some logic*/}
   protected override void Method2(){/*some other logic*/}
}

public class Main
{
    private A;

    public Main(){/*Something*/}

    private void StartB()
    {
       A = new B();
    } 

    private void StartC()
    {
       A = new C();
    } 
}

现在,当我经历一个循环,其中调用 StartB (称为第一个)和 StartC (称为第二个)两个方法之后,当触发了 someevent ,代码尝试在 B类中执行方法(以及后来的C类,我希望。因为它出错所以我无法到达那里它调用B类中的方法),而我希望它只调用 C类中的方法。

我认为,由于事件是在构造函数中订阅的,所以B类方法仍然被解雇,因为它最初是在StartB的调用下订阅的。

问题:
我只想要执行最新实例化的类的方法。

例如:如果按顺序调用 StartB StartC ,则触发 someevent C类中的方法应该只执行。同样的副Versa。怎么做?

我知道我做的事情非常糟糕。非常感谢任何帮助。

2 个答案:

答案 0 :(得分:3)

您不会取消订阅第一个实例中的事件,因此会调用它。如果您不希望它被调用,您需要取消订阅。你可以做这样的事情

class A
{

private static EventHandler lastHandler;

public A()
{
    //warning, not thread safe
    if(lastHandler != null)
    {
        someotherclass.someevent -= lastHandler;
    }
    lastHandler = new EventHandler(HandleEvent);
    someotherclass.someevent += lastHandler;
}

但它看起来很漂亮。在创建新实例之前,最好先实现一个方法(例如IDisposable)来清理最后一个实例。

答案 1 :(得分:1)

如果我理解正确你说你在调用startC之后调用B上的方法并且你不希望这种情况发生吗?

我猜你的问题是someotherclass是一个静态类,或者某个实例以某种方式在所有创建的B和C之间共享 - 在这种情况下,你需要在创建时从someotherclass.someevent取消注册旧的事件处理程序新班级。如果你没有取消注册处理程序,那么someotherclass对象将具有对其注册的B或C对象的引用,因此即使你覆盖了主类中的引用,对象仍然通过引用保持活动状态。事件被触发时仍然被调用。