2012-09-03 22 views
7

ise şu var:Nesne zinciri boyunca olay nasıl ele alınır?

public static void main() { 
    MyClass1 obj = new MyClass1(); 
    obj.Method1(); 
} 
public class MyClass1() { 
    public void Method1() { 
     MyClass2 obj = new MyClass2(); 
     obj.Method1(); 
    } 
} 
public class MyClass2() { 
    public void Method1() { 
     MyClass3 obj = new MyClass3(); 
     obj.Method1(); 
    } 
} 
public class MyClass3() { 
    public void Method1() { 
     // Raise event here that is handled in MyClass1?  
    } 
} 

MyClass3.Method1()MyClass1 işlenme şeklinden bir olayı yükseltebilir?

Bunu yapmak istesem olay kodu nasıl yazılır?

cevap

1

Olay işleme ABC'leri, abonenizin ve yayıncınızın olduğunu varsayar. Bu nedenle, MyClass3'ünüzün herkese açık etkinliğe sahip olmasını isteyebilirsiniz. MyClass1 bu etkinliğe abone olur. Bu karmaşıklık herhangi bir anlam ifade etmez özel kodunda Ancak

- sadece bir geri çağırma işlevi kullanmak için en kolay yolu:

public static void main() { 
    MyClass1 obj = new MyClass1(); 
    obj.Method1(); 
} 
public class MyClass1{ 
    public void Method1() { 
     MyClass2 obj = new MyClass2(); 
     obj.Method1(MyEventHandler); 
    } 

    public void MyEventHandler() { 
    //... 
    } 

} 
public class MyClass2{ 
    public void Method1(Action callback) { 
     MyClass3 obj = new MyClass3(); 
     obj.Method1(callback); 
    } 
} 
public class MyClass3{ 
    public void Method1(Action callback) { 
     // Raise event here that is handled in MyClass1?  
     callback(); 
    } 
} 
+0

'Action 'türü yeni mi? Sadece C# 2.0 kullanıyorum. Bunun yerine bir 'delege' kullanılabilir mi? –

+0

@PaulLassiter Eylem parametreler ve geçersiz dönüş tipi olmayan bir temsilci. Kendinize eşdeğer bir şey tanımlayabilirsiniz. –

+0

public delegate void Action(); –

3

Evet çalıştırılabilir, ancak her seviye aşağıya düzeyleri hakkında bilmez beri Zincirin, her sınıfta etkinlikler oluşturmanız gerekir. Böyle bazıları:

public static void main() { 
    MyClass1 obj = new MyClass1(); 
    obj.MyEvent += (s, e) => { Console.WriteLine("Fired!"); }; 
    obj.Method1(); 
} 

public class MyClass1 { 
    public void Method1() { 
     MyClass2 obj = new MyClass2(); 
     obj.MyEvent += (s, e) => { OnMyEvent(); }; 
     obj.Method1(); 
    } 
    public event EventHandler MyEvent; 
    private void OnMyEvent() { 
     var myEvent = MyEvent; 
     if (myEvent != null) 
      myEvent(this, EventArgs.Empty); 
    } 
} 
public class MyClass2 { 
    public void Method1() { 
     MyClass3 obj = new MyClass3(); 
     obj.MyEvent += (s, e) => { OnMyEvent(); }; 
     obj.Method1(); 
    } 
    public event EventHandler MyEvent; 
    private void OnMyEvent() { 
     var myEvent = MyEvent; 
     if (myEvent != null) 
      myEvent(this, EventArgs.Empty); 
    } 
} 
public class MyClass3 { 
    public void Method1() { 
     // Raise event here that is handled in MyClass1?  
     OnMyEvent(); 
    } 
    public event EventHandler MyEvent; 
    private void OnMyEvent() { 
     var myEvent = MyEvent; 
     if (myEvent != null) 
      myEvent(this, EventArgs.Empty); 
    } 
} 
+0

Yani olayları MyClass1'e zincirlemeniz gerekiyor, bu yüzden MyClass1 MyClass3 tarafından yükseltilen bir olayı başaramıyor? –

+1

Sorununuz, MyClass1'in etkinliği yükseltecek olan MyClass3 örneğini bilmemesi ve bu nedenle etkinliğe abone olamamasıdır. –

+0

@PaulLassiter - Francesco bana onu dövdüler. – Maarten

1

Sen şeyleri bağlamak için aracı sınıfa etkinlik ekleyebilirsiniz. Böyle bir şey: Eğer düşünebilirsiniz

using System; 
using System.Windows.Forms; 

namespace Demo 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      MyClass1 obj = new MyClass1(); 
      obj.Method1(); 
     } 
    } 

    public class MyClass1 
    { 
     public void Method1() 
     { 
      MyClass2 obj = new MyClass2(); 
      obj.SomethingHappened += somethingHappened; 
      obj.Method1(); 
     } 

     private static void somethingHappened(object sender, EventArgs e) 
     { 
      Console.WriteLine("Something happened!"); 
     } 
    } 

    public class MyClass2 
    { 
     public void Method1() 
     { 
      MyClass3 obj = new MyClass3(); 
      obj.SomethingHappened += onSomethingHappened; 
      obj.Method1(); 
     } 

     public event EventHandler SomethingHappened; 

     private void onSomethingHappened(object sender, EventArgs e) 
     { 
      var handler = SomethingHappened; 

      if (handler != null) 
      { 
       handler(this, e); 
      } 
     } 
    } 

    public class MyClass3 
    { 
     public void Method1() 
     { 
      onSomethingHappened(); 
     } 

     private void onSomethingHappened() 
     { 
      var handler = SomethingHappened; 

      if (handler != null) 
      { 
       handler(this, new EventArgs()); 
      } 
     } 

     public event EventHandler SomethingHappened; 
    } 
} 

Bir şey aracı sınıfında "gönderici" argümanı ile ne olduğunu. Sen (yukarıdaki örnekteki gibi) o sinif2 yapabiliriz veya bu gibi özgün gönderen tutabilir: Zincir olay işleyicileri için

private void onSomethingHappened(object sender, EventArgs e) 
{ 
    var handler = SomethingHappened; 

    if (handler != null) 
    { 
     handler(sender, e); 
    } 
} 
2

, sinif2 içinde sözdizimi ekle/kaldır kullanın. MyClass1'den, SomeEvent öğesini ve MyClass3 öğesinde ayarlayın.

public class MyClass1    
{    
    MyClass2 obj = new MyClass2(); 

    public MyClass1() 
    { 
     obj.SomeEvent += obj_SomeEvent; 
    } 

    public void Method1()    
    {      
     obj.Method1();    
    }    

    private static void obj_SomeEvent(object sender, EventArgs e)    
    {    
     Console.WriteLine("Some event fired");    
    }    
} 


public class MyClass2() 
{  
    MyClass3 cls3 = new MyClass3(); 

    public void Method1() 
    {  
     cls3.FireSomeEvent();  
    } 

    public event MyEventHandler SomeEvent 
    { 
     add { this.cls3.SomeEvent += value; } 
     remove { this.cls3.SomeEvent -= value; } 
    } 
} 

public class MyClass3() 
{ 
    public event EventHandler SomeEvent; 

    private void OnSomeEvent() 
    { 
     if (SomeEvent!= null) 
     { 
      SomeEvent(this, new EventArgs()); 
     } 
    } 

    public void FireSomeEvent 
    { 
     OnSomeEvent(); 
    } 
} 
+0

Burada yerel bir değişkeni bir alana dönüştüren "aldatma" youtunuz (MyClass3 in MyClass2). Üstelik işe yaramıyor, çünkü MyClass2 uygulamasının SomeEvent2'sine abone olduğunuzda cls3 boş. Bu, MyClass3'ü MyClass2 Yöntem1'in dışında örneklemeniz gerektiği anlamına gelir, ancak bunun OP'nin beğenebileceği bir şey olduğunu düşünmüyorum. –

+0

@FrancescoBaruchelli - hatayı işaretlediğiniz için teşekkürler. –

1

Her sınıftaki geri arama çözümü ve olay zincirinden kaçınmak istiyorsanız, temel olarak 2 çözümünüz vardır. Birincisi, MyClassX tipi lokal değişkenleri alanlara çevirmekten, yani Chris Gessler'in önerdiği gibi, ancak bu yaklaşımı tamamen takip ederek ve yerel varsları silmekten ibarettir.

public static void main() { 
    MyClass1 obj = new MyClass1(); 
    obj.c2.c3.SomeEvent += obj_SomeEvent;  
    obj.Method1(); 
} 

private static void obj_SomeEvent(object sender, EventArgs e)    
{    
    Console.WriteLine("Some event fired");    
} 

public class MyClass1() { 
    public MyClass2 c2 = new MyClass2(); 

    public void Method1() { 
     c2.Method1(); 
    } 
} 
public class MyClass2() { 
    public MyClass3 c3 = new MyClass3(); 

    public void Method1() { 
     c3.Method1(); 
    } 
} 
public class MyClass3() { 
    public event EventHandler SomeEvent; 

    private void OnSomeEvent() 
    { 
     if (SomeEvent!= null) 
     { 
      SomeEvent(this, new EventArgs()); 
     } 
    } 
    public void Method1() { 
     OnSomeEvent();  
    } 
} 

Diğer seçenek sadece statik olarak MyClass3 olay tanımlamak için (ancak gerçekten uygun olup olmadığını yapmaya çalıştıkları bağlıdır ve yine de sevmiyorum):

public static void main() { 
    MyClass3.SomeEvent += obj_SomeEvent; 
    MyClass1 obj = new MyClass1(); 
    obj.Method1(); 
} 

private static void obj_SomeEvent(object sender, EventArgs e)    
{    
    Console.WriteLine("Some event fired");    
} 

public class MyClass1() { 
    public void Method1() { 
     MyClass2 obj = new MyClass2(); 
     obj.Method1(); 
    } 
} 
public class MyClass2() { 
    public void Method1() { 
     MyClass3 obj = new MyClass3(); 
     obj.Method1(); 
    } 
} 
public class MyClass3() { 
    public static event EventHandler SomeEvent; 

    private void OnSomeEvent(MyClass3 anObj) 
    { 
     if (SomeEvent!= null) 
     { 
      SomeEvent(anObj, new EventArgs()); 
     } 
    } 

    public void Method1() { 
     OnSomeEvent(this);  
    } 
} 
İlgili konular