SORU
25 HAZİRAN 2009, PERŞEMBE


Olay İmza .NET bir Güçlü 'Gönderen Daktilo Kullanarak'?

Ben teklif ediyorum ne takip etmediğini tam olarak farkında .NET kurallar, ve, bu nedenle, muhtemelen bu nedenle tek başına zavallı bir fikir. Ancak, iki olası açılardan bu dikkate almak istiyorum:

(1) kendi geliştirme çalışmalarım için bu kullanarak düşünün, hangi iç amaçlar için 0'dür.

(2) çerçeve tasarımcılar değiştirme veya güncelleme düşünün olabilecek bir kavramdır bu?

''Yerine'', geçerli bir nesne olarak yazmak Gönderen güçlü bir daktilo kullanan bir olay imza kullanarak düşünüyorum Tasarım desen NET. Yani, bu gibi görünüyor bu olay standart bir imza kullanmak yerine

class Publisher
{
    public event EventHandler<PublisherEventArgs> SomeEvent;
}

Güçlü yazılan bir 'Gönderen' aşağıdaki gibidir: parametre . kullanan bir olay imza kullanarak düşünüyorum

, "": . StrongTypedEventHandler ilk tanımlayın

[SerializableAttribute]
public delegate void StrongTypedEventHandler<TSender, TEventArgs>(
    TSender sender,
    TEventArgs e
)
where TEventArgs : EventArgs;

Bu Eylem<TSender, TEventArgs> pek de bir farkı yok; ama StrongTypedEventHandler ile TEventArgs System.EventArgs türeyen uygularız.

Sonraki, bir örnek olarak, aşağıdaki gibi yayıncılık bir sınıfta StrongTypedEventHandler kullanabiliriz

class Publisher
{
    public event StrongTypedEventHandler<Publisher, PublisherEventArgs> SomeEvent;

    protected void OnSomeEvent()
    {
        if (SomeEvent != null)
        {
            SomeEvent(this, new PublisherEventArgs(...));
        }
    }
}

Yukarıdaki düzenleme aboneleri döküm gerektirmeyen güçlü yazılan olay işleyicisi kullanmak için izin istiyorum:

class Subscriber
{
    void SomeEventHandler(Publisher sender, PublisherEventArgs e)
    {   		
        if (sender.Name == "John Smith")
        {
            // ...
        }
    }
}

Bu standart ile sonları fark ettim ki tam olarak .NET olay işleme desen; ancak, bu contravariance abone isterseniz geleneksel bir olay işleme imza kullanmasına izin unutmayın:

class Subscriber
{
    void SomeEventHandler(object sender, PublisherEventArgs e)
    {   		
        if (((Publisher)sender).Name == "John Smith")
        {
            // ...
        }
    }
}

Yani, eğer bir olay işleyicisi gereken abone olmak için olayları farklı (ya da belki de bilinmeyen) nesne türleri, işleyici diye yazın 'Gönderen' parametre olarak 'nesne' için kolu tam genişlik potansiyel Gönderen nesneleri.

Kırma Kongre hafife almak, inan bana ben de olmayan bir şey) dışında ben bunda herhangi bir olumsuzlukları düşün.

Bazı CLS uyum sorunu burada da olabilir. Bu, Visual Basic çalıştırın .2008 0 iyi (test ettim) NET, ama Visual Basic eski sürümleri inanıyorum .2005 ile NET temsilci kovaryans ve contravariance yok.[Edit: bu test ettik ve onaylandı: 2005 VB.NET ve bu idare altında, ama 2008 VB.NET 0 iyi. "#2", aşağıda.] DüzenlemeBaşka da olabilir .Ayrıca bu sorun NET dilleri, emin değilim.

Ama herhangi bir dil C dışında kendimi geliştirmek görmüyorum# veya Visual Basic .NET ve C için kısıtlama yok# için VB.NET .NET Çerçeve ve yukarıdaki 3.0. (Bu noktada tekrar 2.0 olacak, dürüst olmak gerekirse hayal edemiyorum.)

Herkesten bu sorun var mı? Ya da bu sadece Kongre ile insanların mideleri dönüş yapar o kadar.

İşte bulduğum bazı ilgili bağlantılar:

(1) Event Design Guidelines [MSDN 3.5]

(2) C# simple Event Raising - using “sender” vs. custom EventArgs [StackOverflow 2009]

(3) Event signature pattern in .net [StackOverflow 2008]

Bu konuda hiç kimsenin ve herkesin fikrini merak ediyorum...

Şimdiden teşekkürler

Mike

Edit #1:Bu Tommy Carlier's post yanıt

Burada güçlü yazılan her iki olay işleyicileri ve 'Gönderen' co-var bu yaklaşımı ile parametre. nesne için geçerli standart olay işleyicileri gösteren tam bir çalışma örneği. Kopyala-yapıştır Kodu ve çalıştırın.

namespace csScrap.GenericEventHandling
{
    class PublisherEventArgs : EventArgs
    {
        // ...
    }

    [SerializableAttribute]
    public delegate void StrongTypedEventHandler<TSender, TEventArgs>(
        TSender sender,
        TEventArgs e
    )
    where TEventArgs : EventArgs;

    class Publisher
    {
        public event StrongTypedEventHandler<Publisher, PublisherEventArgs> SomeEvent;

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

    class StrongTypedSubscriber
    {
        public void SomeEventHandler(Publisher sender, PublisherEventArgs e)
        {
            MessageBox.Show("StrongTypedSubscriber.SomeEventHandler called.");
        }
    }

    class TraditionalSubscriber
    {
        public void SomeEventHandler(object sender, PublisherEventArgs e)
        {
            MessageBox.Show("TraditionalSubscriber.SomeEventHandler called.");
        }
    }

    class Tester
    {
        public static void Main()
        {
            Publisher publisher = new Publisher();

            StrongTypedSubscriber strongTypedSubscriber = new StrongTypedSubscriber();
            TraditionalSubscriber traditionalSubscriber = new TraditionalSubscriber();

            publisher.SomeEvent  = strongTypedSubscriber.SomeEventHandler;
            publisher.SomeEvent  = traditionalSubscriber.SomeEventHandler;

            publisher.OnSomeEvent();
        }
    }
}

Edit #2:Bu buraya nasıl uygulanır kovaryans ve contravariance ilgili Andrew Hare's statement yanıt. C delegeler# dili sadece hissediyorum o kadar uzun süre kovaryans ve contravariance sahip "" değil ama. iç Hatta CLR, bilmiyorum ama Visual Basic etkin olan başka bir şey de olabilir .NET kadar delege için kovaryans ve contravariance yeteneği alamadım .NET Çerçeve 3.0 (VB.NET 2008). Ve sonuç olarak, Visual için Basic.NET .NET 2.0 ve altı bu yaklaşım kullanmak mümkün olmaz.

Örneğin, yukarıdaki örneği aşağıdaki gibi: VB.NET çevrilebilir

Namespace GenericEventHandling
    Class PublisherEventArgs
        Inherits EventArgs
        ' ...
        ' ...
    End Class

    <SerializableAttribute()> _
    Public Delegate Sub StrongTypedEventHandler(Of TSender, TEventArgs As EventArgs) _
        (ByVal sender As TSender, ByVal e As TEventArgs)

    Class Publisher
        Public Event SomeEvent As StrongTypedEventHandler(Of Publisher, PublisherEventArgs)

        Public Sub OnSomeEvent()
            RaiseEvent SomeEvent(Me, New PublisherEventArgs)
        End Sub
    End Class

    Class StrongTypedSubscriber
        Public Sub SomeEventHandler(ByVal sender As Publisher, ByVal e As PublisherEventArgs)
            MessageBox.Show("StrongTypedSubscriber.SomeEventHandler called.")
        End Sub
    End Class

    Class TraditionalSubscriber
        Public Sub SomeEventHandler(ByVal sender As Object, ByVal e As PublisherEventArgs)
            MessageBox.Show("TraditionalSubscriber.SomeEventHandler called.")
        End Sub
    End Class

    Class Tester
        Public Shared Sub Main()
            Dim publisher As Publisher = New Publisher

            Dim strongTypedSubscriber As StrongTypedSubscriber = New StrongTypedSubscriber
            Dim traditionalSubscriber As TraditionalSubscriber = New TraditionalSubscriber

            AddHandler publisher.SomeEvent, AddressOf strongTypedSubscriber.SomeEventHandler
            AddHandler publisher.SomeEvent, AddressOf traditionalSubscriber.SomeEventHandler

            publisher.OnSomeEvent()
        End Sub
    End Class
End Namespace

VB.NET 2008 0 iyi çalıştırabilirsiniz. Ama şimdi sadece emin olmak için VB.NET 2005, denedim, ve, belirten derleme değildir:

Yöntem 'Public Sub SomeEventHandler(Nesne Olarak Gönderen, e Olarak vbGenericEventHandling.GenericEventHandling.PublisherEventArgs)' aynı imza gibi yok temsilci 'Temsilci Sub StrongTypedEventHandler(TSender, Sistem Olarak TEventArgs.EventArgs)(sender E Olarak, Yayıncı olarak, PublisherEventArgs)'

Temel olarak, temsilci VB.NET sürüm 2005 ve altında değişmeyen vardır. Aslında düşünce bu fikir birkaç yıl önce, ama VB.NET edemeyişinin için anlaşma ile bu rahatsız etti beni... Ama şimdi taşındı sağlam C# ve VB.NET şimdi başa, yani, iyi, bu yüzden bu yazı.

Edit: Update #3

Tamam, oldukça başarılı bir şekilde bunu bir süredir kullanıyorum. Gerçekten güzel bir sistem. Kendi adıma karar verdim"""", aşağıdaki gibi tanımlanır . GenericEventHandler olarak StrongTypedEventHandler

[SerializableAttribute]
public delegate void GenericEventHandler<TSender, TEventArgs>(
    TSender sender,
    TEventArgs e
)
where TEventArgs : EventArgs;

Bu yeniden adlandırma dışında, tam da yukarıda anlatıldığı gibi uygulanır.

Birleşik Devletleri: CA1009, FxCop kural üzerinde yolculuk yapar

"Kongre tarafından .NET olaylar iki olay belirttiğiniz parametreleri gönderen ve olay verileri. Olay işleyicisi imza bu formu takip etmelidir: void MyEventHandler( object sender, EventArgs e). 'Gönderen' parametresi her tür Sistem.Hatta nesne eğer daha fazla istihdam imkanı varsa belirli bir türü. 'E' parametresi yazın Sistem her zaman.EventArgs. Olay veri sağlayan olaylar Sistemi kullanmak gerekir.EventHandler tür temsilci. Olay işleyicileri dönüş geçersiz her olay göndermek o kadar birden çok hedef yöntem. Herhangi bir değer kaybedilecek bir hedef tarafından döndürülen ilk görüşme."

Elbette, bunu biliyoruz, ve zaten kurallarını çiğniyor. (Tüm olay işleyicileri standart 'nesne Gönderen:" onların imza Eğer -- Eğer tercih edilen bu olmayan bir son dakika değişikliği.) kullanabilirsiniz

SuppressMessageAttribute kullanımı işe yarıyor yani:

[SuppressMessage("Microsoft.Design", "CA1009:DeclareEventHandlersCorrectly",
    Justification = "Using strong-typed GenericEventHandler<TSender, TEventArgs> event handler pattern.")]

Bu yaklaşım gelecekte bir noktada standart olur umarım. Gerçekten çok güzel çalışıyor.

Tüm görüşler çocuklar için teşekkürler, gerçekten teşekkür ederim...

Mike

CEVAP
25 Kasım 2010, PERŞEMBE


Microsoft benzer bir örnek şimdi MSDN'DE olarak bu aldı gibi görünüyor:

Generic Delegates

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • ExcelIsFun

    ExcelIsFun

    16 ŞUBAT 2008
  • Miles Fisher

    Miles Fisher

    8 NİSAN 2009
  • ShayLoss

    ShayLoss

    5 Kasım 2009