2011-06-29 17 views
6

nasıl burada anonim yöntemi kullanarak önlemek istediğini eğer yöntemini"Dinamik" etkinlik aboneliğinde anonim yöntemler nasıl önlenir?

private void ListenToPropertyChangedEvent(INotifyPropertyChanged source, 
              string propertyName) 
{ 
    source.PropertyChanged += (o, e) => 
    { 
     if (e.PropertyName == propertyName) 
      MyMagicMethod(); 
    }; 
} 

planı ayrı olabilir?

+0

Buradaki hile, anonim bir yöntem değil - kullanılan * kapanma *. Akla gelen tek diğer yol, bir 'PropertyName' değişkenini/özelliğini ya da benzerini ve' OnPropertyChanged' olay işleyicisini uygulayan yeni bir nesne oluşturmaktır. –

+0

@pst: Yorum için teşekkürler. Sanırım buradakiler hakkında hala biraz bulanıkım. Http://csharpindepth.com/Articles/Chapter5/Closures.aspx adresini şimdi okuyun. =) – Jens

cevap

4

örtülü açıkça lambda tarafından oluşturulan kapatma uygulayın:

private void ListenToPropertyChangedEvent(INotifyPropertyChanged source, 
              string propertyName) 
{ 
    var listener = new MyPropertyChangedListener(propertyName); 
    source.PropertyChanged += listener.Handle; 
} 

class MyPropertyChangedListener 
{ 
    private readonly string propertyName; 

    public MyPropertyChangedListener(string propertyName) 
    { 
     this.propertyName = propertyName; 
    } 

    public void Handle(object sender, PropertyChangedEventArgs e) 
    { 
     if (e.PropertyName == this.propertyName) 
     { 
      // do something 
     } 
    } 
} 
+0

Teşekkürler! Yukarıdaki lambdamın gerçekten içsel anlamı nedir? İlginç. =) – Jens

1
Sen takip ettiğinizi örneklerinin bir sözlük kullanan tüm örnekleri için tek olay işleyicisi alarak bu işleyebilir

:

private Dictionary<INotifyPropertyChanged, List<string>> sourceMap = 
    new Dictionary<INotifyPropertyChanged, List<string>>(); 

private void ListenToPropertyChangedEvent(INotifyPropertyChanged source, 
              string propertyName) 
{ 
    if (sourceMap.ContainsKey(source)) 
     sourceMap[source].Add(propertyName); 
    else 
    { 
     source.PropertyChanged += source_PropertyChanged; 
     sourceMap[source] = new List<string> { propertyName }; 
    } 
} 

void source_PropertyChanged(object sender, PropertyChangedEventArgs e) 
{ 
    var source = sender as INotifyPropertyChanged; 
    var list = sourceMap[source]; 
    if (list.Contains(e.PropertyName)) 
     MyMagicMethod(); 
} 

Bu sürümde herhangi bir hata denetimi ya da kaldırma bulunmamakta, ancak bu teknik tekniğini göstermektedir. aynı kaynak'dan birden çok özellik dinlerseniz özellikle değerlidir. Bunun nedeni, örnek başına yalnızca PropertyChanged olayına tek bir işleyici ekler.

+0

Cevabınız için teşekkürler! Gerçekten aynı kaynaktan birden fazla mülk dinleyebilirim. Bu yaklaşımla ilgili biraz daha fazla defter tutma söz konusu olabilir, çünkü kaynakları sözlükte atıfta bulunularak toplanan çöplerden korumak istemiyorum, ancak bunlar yönetilebilir. – Jens

0

ben sen başarmak için çalışıyor tam olarak emin değilim ya neden anonim yöntemleri kullanmak istemiyorum, ama daha genel bir şey yapabilirsiniz:

private PropertyChangedEventHandler GetHandler 
     (Func<PropertyChangedEventArgs, bool> test, Action toInvoke) 
    { 
     return new PropertyChangedEventHandler(
      (o, e) => 
      { 
       if (test(e)) 
       toInvoke(); 
      }); 
    } 

Sonra şöyle kullanabilirsiniz:

source.PropertyChanged += GetHandler     
      (
       p => p.PropertyName == propertyName, MyMagicMethod 
      ); 

Bu şekilde if testiniz ve hedef metod grubunuz kolayca değiştirilebiliyor. Etkinlik işleyiciniz de anonimden çok yazılmıştır.

+0

İş arkadaşlarım anonim yöntemlerle rahat değiller, bu yüzden onları mümkün olduğunca engellemeye çalışıyorum. – Jens

+0

Teknik olarak PropertyChangedEventHandler özellikle PropertyChangedEventArgs yaymak olaylar dinlemek için tasarlanmış bir temsilci, bu nedenle her zaman sen, anonim bir yöntemin kullanılmasını kaçınır gibi bir kesinlikle yazılan EventHandler böyle kullanmak sadece bir yöntem grubunda geçmesi şartıyla hangi bir fonksiyonu olan (eksi ödemeyi hemen yürütmesini öyle bc parantez,) ne zaman olay yangınları aramak istiyorum. Bir EventHandler zaten ne yaptığını şu - Ben olay dinleme kapsüller tamamen yeni bir sınıf oluşturmak için onun gerekli söyleyemem. –