2010-07-15 7 views
8

Birden fazla kullanımının DRY ilkesini ihlal etmesinden başka, bu tek liner için olumsuzlukları görebiliyor musunuz? Açıkca görünüyor ama başkalarını görmediğimi görmem, bunun bir dezavantajı olup olmadığını merak etmemi sağlıyor.Tek Liner: WeakReference-to-a-Lambda Olay İşleyicisi

Bu kod bir yöntem için WeakReference oluşturur ve daha sonra başvurunun hedefini tetikleyen bir olay işleyicisini kaydeder.

SomeEvent += (sender, e) => ((Action)(new WeakReference((Action)ProcessEvent)).Target)(); 

sayesinde
Ben

+0

Sorunuzu/yanıtı gördünüz mü [burada] (http://stackoverflow.com/questions/1747235/weak-event-handler-model-for-use-with-lambdas)? Tek liner değil, ama * düşünüyorum * işe yarıyor ... – Benjol

cevap

11

Bu modelin beklediğiniz gibi yaptıklarını sanmıyorum. Bellek sızıntılarını önlemek için etkin nesneyi bir referans tutmasını engellemeye mi çalışıyorsunuz? Lambda ifadesi, ProcessEvent değerini değerlendirmek için this değerini yakalar (ProcessEvent bir örnek yöntemdir), böylece sızıntıya sahip olursunuz. Bu kod, SomeEvent += (sender, e) => ProcessEvent(); ile aynıdır.

Sen (ayrıca ne istediğinizi değil) daha böyle bir şey yapmak için çalışıyor olabilir: Eğer güçlü bir başvuru olmaz bu yüzden,

var reference = new WeakReference((Action)ProcessEvent); 
SomeEvent += (sender, e) => ((Action)reference.Target)(); 

Şimdi lambda ifadesi WeakReference yakalayacaktır this. Ne yazık ki, hiçbir şey ProcessEvent tarafından oluşturulan temsilci referans değil, bu yüzden this hala hayatta olsa bile bir sonraki GC üzerinde kaldırılacaktır. (Bu ayrıca Hedefin boş olup olmadığını da kontrol etmez).

Böyle bir şey deneyebilirsiniz: bu gibi kullanmak sonra

public EventHandler MakeWeakHandler(Action action, Action<EventHandler> remove) 
{ 
    var reference = new WeakReference(action.Target); 
    var method = action.Method; 
    EventHandler handler = null; 
    handler = delegate(object sender, EventArgs e) 
    { 
     var target = reference.Target; 
     if (target != null) 
     { 
      method.Invoke(target, null); 
     } 
     else 
     { 
      remove(handler); 
     } 
    }; 
    return handler; 
} 

ve: ProcessEvent alıcıya zayıf başvuru tutacak ve otomatik olarak olayı kaldıracak

SomeEvent += MakeWeakHandler(ProcessEvent, h => SomeEvent -= h); 

Olaydan toplayıcı, olay düzenli olarak yükseltildiği sürece bellek sızıntılarını önlemesi gereken toplandı.

+0

Bu herhangi bir etkinlik için işe yaramıyor. Örneğin, * EventArgs yerine PropertyChangedEventArgs ve EventHandler özelliklerinin PropertyChangedEventHandler ile değiştirilmesi gibi * kesin * olayı için bunu özelleştirmeniz gerekir. Türleri geçirebileceğiniz ancak işe yaramadığı bir genel sürüm oluşturmaya çalıştım. –

0

Onun çok okunabilir değil. Ve adım adım hata ayıklamak zorunda kalırsanız, bu eylemlerden herhangi biri başarısız olabilir, ancak bu tek satır başarısız olur. Ayrıca, yalnızca yığın izinde başvurulan tek bir satırı elde edersiniz.

Genelde bakım için tek bir satırda çok fazla şey yapmaktan kaçınmak istersiniz.