मुझे पूरी तरह से पता है कि मैं जो प्रस्ताव कर रहा हूं वह .NET दिशानिर्देशों का पालन नहीं करता है, और इसलिए, शायद अकेले इस कारण से एक खराब विचार है। हालांकि, मैं दो संभावित दृष्टिकोणों से इस पर विचार करना चाहूंगा:
(1) क्या मुझे अपने स्वयं के विकास कार्यों के लिए इसका उपयोग करने पर विचार करना चाहिए, जो आंतरिक उद्देश्यों के लिए 100% है।
(२) क्या यह एक अवधारणा है जिसे रूपरेखा डिजाइनर बदलने या अद्यतन करने पर विचार कर सकते हैं?
मैं एक घटना हस्ताक्षर का उपयोग करने के बारे में सोच रहा हूं जो एक मजबूत टाइप किए गए 'प्रेषक' का उपयोग करता है, इसके बजाय इसे 'ऑब्जेक्ट' के रूप में टाइप करना है, जो कि वर्तमान .NET डिज़ाइन पैटर्न है। इसके बजाय, मानक ईवेंट हस्ताक्षर का उपयोग करने के बजाय ऐसा दिखता है:
class Publisher
{
public event EventHandler<PublisherEventArgs> SomeEvent;
}
मैं एक घटना हस्ताक्षर का उपयोग करने पर विचार कर रहा हूं जो एक मजबूत-टाइप किए गए 'प्रेषक' पैरामीटर का उपयोग करता है, इस प्रकार है:
सबसे पहले, एक "स्ट्रांगपाइपडेंटहैंडलर" परिभाषित करें:
[SerializableAttribute]
public delegate void StrongTypedEventHandler<TSender, TEventArgs>(
TSender sender,
TEventArgs e
)
where TEventArgs : EventArgs;
यह सब एक एक्शन <TSender, TEventArgs> से अलग नहीं है, लेकिन इसका उपयोग करने से StrongTypedEventHandler
, हम यह लागू करते हैं कि TEventArgs से व्युत्पन्न हैSystem.EventArgs
।
अगला, एक उदाहरण के रूप में, हम एक प्रकाशन वर्ग में StrongTypedEventHandler का उपयोग इस प्रकार कर सकते हैं:
class Publisher
{
public event StrongTypedEventHandler<Publisher, PublisherEventArgs> SomeEvent;
protected void OnSomeEvent()
{
if (SomeEvent != null)
{
SomeEvent(this, new PublisherEventArgs(...));
}
}
}
उपरोक्त व्यवस्था ग्राहकों को एक मजबूत-टाइप ईवेंट हैंडलर का उपयोग करने में सक्षम बनाएगी जिसे कास्टिंग की आवश्यकता नहीं थी:
class Subscriber
{
void SomeEventHandler(Publisher sender, PublisherEventArgs e)
{
if (sender.Name == "John Smith")
{
// ...
}
}
}
मुझे पूरी तरह से एहसास है कि यह मानक .NET इवेंट-हैंडलिंग पैटर्न के साथ टूटता है; हालाँकि, इस बात का ध्यान रखें कि यदि वांछित हो तो एक ग्राहक एक पारंपरिक ईवेंट हैंडलिंग सिग्नेचर का उपयोग करने में सक्षम होगा:
class Subscriber
{
void SomeEventHandler(object sender, PublisherEventArgs e)
{
if (((Publisher)sender).Name == "John Smith")
{
// ...
}
}
}
यही है, अगर एक इवेंट हैंडलर को असमान (या शायद अज्ञात) ऑब्जेक्ट प्रकारों से घटनाओं की सदस्यता लेने की आवश्यकता होती है, तो संभावित प्रेषक ऑब्जेक्ट्स की पूरी चौड़ाई को संभालने के लिए हैंडलर 'प्रेषक' पैरामीटर को 'ऑब्जेक्ट' के रूप में टाइप कर सकता है।
ब्रेकिंग कन्वेंशन के अलावा (जो कुछ ऐसा है जिसे मैं हल्के में नहीं लेता हूं, मेरा विश्वास करो) मैं इसके लिए किसी भी डाउनडाइड के बारे में नहीं सोच सकता।
यहां कुछ सीएलएस अनुपालन मुद्दे हो सकते हैं। यह Visual Basic .NET 2008 100% ठीक है (मैंने परीक्षण किया है) में चलता है, लेकिन मेरा मानना है कि 2005 के माध्यम से Visual Basic .NET के पुराने संस्करणों में प्रतिनिधि सहसंयोजक और विरोधाभासी नहीं है। [संपादित करें: मैंने इसका परीक्षण किया है, और इसकी पुष्टि की गई है: VB.NET 2005 और नीचे इसे संभाल नहीं सकता है, लेकिन VB.NET 2008 100% ठीक है। नीचे "संपादित करें # 2" देखें।] ऐसी अन्य .NET भाषाएँ हो सकती हैं, जिनके साथ भी यह समस्या है, मुझे यकीन नहीं हो रहा है।
लेकिन मैं अपने आप को C # या Visual Basic .NET के अलावा किसी भी भाषा के लिए विकसित नहीं देखता, और मुझे .NET फ्रेमवर्क 3.0 और इसके बाद के संस्करण के लिए इसे C # और VB.NET तक सीमित करने में कोई आपत्ति नहीं है। (मैं इस बिंदु पर 2.0 तक वापस जाने की कल्पना नहीं कर सकता था, ईमानदार होने के लिए।)
किसी और को इस के साथ एक समस्या के बारे में सोच सकते हैं? या यह केवल सम्मेलन के साथ इतना टूट जाता है कि यह लोगों के पेट को मोड़ देता है?
यहाँ कुछ संबंधित लिंक दिए गए हैं जिन्हें मैंने पाया है:
(1) इवेंट डिजाइन दिशानिर्देश [MSDN 3.5]
(2) C # सिंपल इवेंट राइज़िंग - "प्रेषक" बनाम कस्टम EventArgs का उपयोग करना [StackOverflow 2009]
(3) .net [StackOverflow 2008] में इवेंट सिग्नेचर पैटर्न
मुझे इस पर किसी की भी और सभी की राय में दिलचस्पी है ...
अग्रिम में धन्यवाद,
माइक
# 1 संपादित करें: यह टॉमी कार्लाइर की पोस्ट के जवाब में है :
यहां एक पूर्ण कार्य करने वाला उदाहरण दिखाया गया है कि मजबूत-टाइप किए गए ईवेंट हैंडलर और वर्तमान मानक ईवेंट हैंडलर दोनों एक 'ऑब्जेक्ट प्रेषक' पैरामीटर का उपयोग करते हैं जो इस दृष्टिकोण के साथ सह-अस्तित्व में हो सकते हैं। आप कोड में कॉपी-पेस्ट कर सकते हैं और उसे एक रन दे सकते हैं:
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();
}
}
}
# 2 संपादित करें: यह एंड्रयू हारे के सहसंयोजक और विरोधाभासी के बयान के जवाब में है और यह यहां कैसे लागू होता है। C # भाषा में प्रतिनिधि इतने लंबे समय के लिए सहसंयोजक और विरोधाभासी रहे हैं कि यह सिर्फ "आंतरिक" लगता है, लेकिन ऐसा नहीं है। यह कुछ ऐसा भी हो सकता है जो सीएलआर में सक्षम है, मुझे नहीं पता, लेकिन विजुअल बेसिक .NET को अपने प्रतिनिधियों के लिए .NET फ्रेमवर्क 3.0 (VB.NET 2008) तक कोविरियस और कंट्रोवर्सी क्षमता नहीं मिली। और परिणामस्वरूप, .NET 2.0 और नीचे के लिए Visual Basic.NET इस दृष्टिकोण का उपयोग करने में सक्षम नहीं होगा।
उदाहरण के लिए, उपरोक्त उदाहरण VB.NET में अनुवादित किया जा सकता है:
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 इसे 100% ठीक चला सकता है। लेकिन मैंने अब इसे VB.NET 2005 पर परीक्षण किया है, बस सुनिश्चित करने के लिए, और यह संकलित नहीं करता है:
विधि 'सार्वजनिक उप SomeEventHandler (प्रेषक ऑब्जेक्ट के रूप में, e as vGGenericEventHandling.GenericEventHandling.PublisherEventArgs)' के पास प्रतिनिधि के रूप में एक ही हस्ताक्षर नहीं है, जो 'डेलिगेट सब स्ट्रॉन्गटेडइवेंटहैंडलर (TSender, TEventArgs As System.EventAsgs' के रूप में है)। '
मूल रूप से, प्रतिनिधि VB.NET 2005 और उससे नीचे के संस्करणों में अपरिवर्तनीय हैं। मैं वास्तव में कुछ साल पहले इस विचार के बारे में सोचता था, लेकिन इस परेशान से निपटने के लिए VB.NET की अक्षमता ने मुझे परेशान कर दिया ... लेकिन मैंने अब C # को ठोस रूप से स्थानांतरित कर दिया है, और VB.NET अब इसे संभाल सकता है, इसलिए, अच्छी तरह से, इसलिए ये पद।
संपादित करें: # 3 अपडेट करें
ठीक है, मैं इसे थोड़ी देर के लिए सफलतापूर्वक उपयोग कर रहा हूं। यह वास्तव में एक अच्छी प्रणाली है। मैंने अपने "StrongTypedEventHandler" को "GenericEventHandler" के रूप में नामित करने का फैसला किया, इस प्रकार है:
[SerializableAttribute]
public delegate void GenericEventHandler<TSender, TEventArgs>(
TSender sender,
TEventArgs e
)
where TEventArgs : EventArgs;
इस नामकरण के अलावा, मैंने इसे ठीक उसी तरह लागू किया जैसा कि ऊपर चर्चा की गई है।
यह FxCop नियम CA1009 पर यात्रा करता है, जो बताता है:
"कन्वेंशन द्वारा, .NET इवेंट्स में दो पैरामीटर होते हैं जो ईवेंट भेजने वाले और ईवेंट डेटा को निर्दिष्ट करते हैं। ईवेंट हैंडलर सिग्नेचर को इस फॉर्म का पालन करना चाहिए: शून्य MyEventHandler (ऑब्जेक्ट प्रेषक, EventArgs e)। 'प्रेषक' पैरामीटर हमेशा System.Object का प्रकार होता है। भले ही यह अधिक विशिष्ट प्रकार को नियोजित करने के लिए संभव हो। 'e' पैरामीटर हमेशा प्रकार का System.EventArgs होता है। ईवेंट डेटा प्रदान नहीं करने वाली ईवेंट्स को System.EventHandler प्रतिनिधि प्रकार का उपयोग करना चाहिए। ईवेंट हैंडलर शून्य को वापस भेजते हैं जो वे भेज सकते हैं। प्रत्येक घटना कई लक्ष्य विधियों के लिए। किसी लक्ष्य द्वारा लौटाए गए मूल्य को पहली कॉल के बाद खो दिया जाएगा। "
बेशक, हम यह सब जानते हैं, और वैसे भी नियमों को तोड़ रहे हैं। (सभी ईवेंट हैंडलर किसी भी मामले में पसंद किए जाने पर अपने हस्ताक्षर में मानक 'ऑब्जेक्ट सेंडर' का उपयोग कर सकते हैं - यह एक गैर-परिवर्तनशील बदलाव है।)
तो SuppressMessageAttribute
चाल का उपयोग करता है:
[SuppressMessage("Microsoft.Design", "CA1009:DeclareEventHandlersCorrectly",
Justification = "Using strong-typed GenericEventHandler<TSender, TEventArgs> event handler pattern.")]
मुझे उम्मीद है कि यह दृष्टिकोण भविष्य में किसी बिंदु पर मानक बन जाएगा। यह वास्तव में बहुत अच्छी तरह से काम करता है।
आपके सभी राय लोगों के लिए धन्यवाद, मैं वास्तव में इसकी सराहना करता हूं ...
माइक
oh hi this my hom work solve it plz :code dump:
सवाल नहीं है, लेकिन एक सवाल जो हम सीखते हैं ।
EventHandler<,>
से GenericEventHandler<,>
। EventHandler<>
बीसीएल में पहले से ही जेनेरिक है जिसे सिर्फ इवेंटहैंडलर नाम दिया गया है। तो EventHandler एक अधिक सामान्य नाम है और प्रतिनिधियों ने ओवरलोड का समर्थन किया है