2009-01-12 22 views
8

Karşılaştığım ortak bir sorun olmalı. Birkaç farklı sınıfa abone olabilen bir olayım olduğunda, bu sınıflardan biri tarafından atılan bir istisna geri arama zincirini öldürecektir; Geri çağırmaların hangi sırayla gerçekleştirildiğini önceden bildiğimden, bu, bazı sınıflar için öngörülemeyen durum değişikliklerine yol açabilir ve başkaları için olmayabilir.Delege zincirimi çökerterek özel durumları nasıl durdurabilirim?

İncil'de (CLR via C#, C# 2.0 kullanıyorum), bunun için MulticastDelegate.GetInvocationList'u kullanmanın kısa bir paragrafı var, ama başka bir şey yok. Yani sorum şu: Bununla başa çıkmanın en iyi yolu nedir? Her olayım olduğunda MulticastDelegate.GetInvocationList kullanmalı mıyım? Ya da delege zincirinin bir parçası olarak çağrılabilecek tüm yöntemleri bir tür geri alma mekanizması içine almam mı gerekiyor? Neden tüm bu seçenekler C# içinde kullanımı çok kolay olan basit olay/delege modeline göre çok karmaşık? Ve basit yolu, bozuk durumla bitmeden nasıl kullanabilirim?

Teşekkürler!

+0

not Yorumunuzu yazın –

cevap

11

Sadece bir temsilci çağırırsanız, sırayla tüm hedef yöntemleri çağırır. Eğer tek tek çalıştırmak istiyorsanız GetInvocationList kullanmak gerekir - örneğin: Bireysel hedefin hatadan sonra devam etmek her

  • döndürülen değerini yakalamak için

    • her
    • sonra Cancel kontrol etmek

    Kullanmanın en iyi yolu olarak: nasıl davranmasını istersiniz? Bana belli değil ... Örneğin, bu oldukça iyi bir uzantısı yöntemi uygun olabilecek:

    static void InvokeIgnoreErrors(this EventHandler handler, 
         object sender) { 
        if(handler != null) { 
         foreach(EventHandler subHandler in handler.GetInvocationList()) { 
          subHandler(sender, EventArgs.Empty); 
         } 
        } 
    } 
    

    Sonra sadece myHandler.InvokeIgnoreErrors(this); (örneğin) çağırabilir.

    başka örnek olabilir: Birinci olaydan sonra durur

    static bool InvokeCheckCancel(this CancelEventHandler handler, 
         object sender) { 
        if(handler != null) { 
         CancelEventArgs args = new CancelEventArgs(false); 
         foreach(CancelEventHandler subHandler in handler.GetInvocationList()) { 
          subHandler(sender, args); 
          if(args.Cancel) return true; 
         } 
        } 
        return false; 
    } 
    

    iptali talep eder.

  • +0

    Tamam, bu uzatma yöntemleri için güzel bir kullanım gibi görünüyor. Maalesef C# 2.0'da sıkışıp kaldım - herhangi bir fikri burada nasıl zarif bir şekilde yapabilirim? Teşekkürler! –

    +1

    Sadece statik bir yöntem kullanın, o zaman. "Bu" kaldırmak ve sadece YourUtilityClass.InvokeIgnoreErrors (myHandler, bu) kullanın; –

    1

    Olayları nasıl çağırdığınızı değiştirmek yerine, olay işleyicilerinizi gözden geçirmeniz gerektiğini düşünüyorum. Benim düşünceme göre olay eylemci yöntemleri her zaman yazılmalı, böylece "güvenli" ve asla istisnaların yayılmasına izin verilmemelidir. Bu olay, olayın harici kod tarafından çağrıldığı GUI kodunda ele alındığında, ancak her zaman için iyi bir alışkanlık olduğunda, özellikle önemlidir.

    +0

    'Propagate' ile ne demek istiyorsun? Açıkçası, # 1 ve # 2 yöntemlerinde (ancak yöntem # 4'de değil) gerçekleştirilen tüm değişiklikleri geri almak zorunda kalabileceğimi düşündüğümden, eğer çökmüşse beni bilgilendirmek için temsilci zincirimde 3. yönteme ihtiyacım olabilir. –

    +0

    Ardından gözlemci desenini yanlış kullanıyorsunuz, olayları kullanma noktası gevşek birleştirilmiş bir bildirim sistemi. Burada sadece abonelerin ve yayıncıların birbirlerinin uygulama ayrıntılarını bilmeleri gerekmiyor, aboneler de diğer abonelerle ilgili uygulama ayrıntılarını bilmelidir. –

    +0

    Bu, delegasyonu doğrudan Marc'ın tarif ettiği gibi çağırmaktan ziyade, çağrı listesini kullanmak isteyeceğiniz durumlar olduğunu söyledi. –

    İlgili konular