2011-04-08 11 views
7

मैं कक्षा पुस्तकालय के भीतर ऑब्जेक्ट्स को आउटपुट करने के बारे में चिंता किए बिना संदेशों को "आउटपुट" करने की क्षमता प्रदान करना चाहता हूं। क्लास लाइब्रेरी को कंसोल ऐप, विनफॉर्म या डब्ल्यूपीएफ विंडोज़ एप्लिकेशन या वेब पेज में इस्तेमाल किया जा सकता है।क्या उपयोग करें? प्रतिनिधि, घटना, या Func <T>?

मैं मूल रूप से निर्णय लेता था कि मैं इसे संभालने के लिए एक प्रतिनिधि का उपयोग करूंगा। मैंने कक्षाओं का उपयोग करके इसे कार्यान्वित किया लेकिन संकलक को प्रतिनिधि को पसंद नहीं आया जब मैंने प्रतिनिधियों को एक इंटरफेस में डालने का प्रयास किया कि इनमें से प्रत्येक वस्तु निहित है।

मुझे पता चला कि मैं प्रतिनिधि को इंटरफ़ेस से बाहर ले जा सकता हूं और फिर संकलित करने में सक्षम था लेकिन मुझे यकीन नहीं है कि यह पूरा करने के लिए मैं क्या कर रहा हूं .. यह भी एक कड़वाहट जैसा लगता है इसलिए मैं पूछना चाहता था यदि आप में से किसी अलग विचारों यह पूरा करने के लिए है ...

इंटरफ़ेस:

namespace Test 
{ 
    using System; 
    using System.Xml.Linq; 

    public interface IAction 
    { 
    DisplayMessageDelegate DisplayMessage(string message); 
    void Execute(); 
    XElement Serialize(XName elementName); 
    } 

    public delegate void DisplayMessageDelegate(string message); 
} 

वहाँ से, मुझे यकीन है कि कैसे इस व्यवहार को लागू करने की नहीं कर रहा हूँ: (BTW, मुझे पता है कि इस कोड को नहीं होगा संकलित करें ...)

public class ActionClass1 : IAction 
{ 
    // Other methods not shown... 
    void Execute() 
    { 
    if (this.DisplayMessage != null) 
    { 
     this.DisplayMessage(“Hello”); 
    } 
    } 
} 

public class ConsoleClass 
{ 
    ActionClass1 class1 = new ActionClass1(); 
    class1.DisplayMessage = { x => Console.WriteLine(x); }; 
} 

public class WinFormClass 
{ 
    ActionClass1 class1 = new ActionClass1(); 
    Class1.DisplayMessage = {x => DisplayTextBox.Text = x; }; 
} 

उत्तर

11

यदि आप Execute पर एक कॉल का जवाब देने के लिए एकाधिक प्रतिनिधियों को हुक करने की क्षमता चाहते हैं, तो मैं निश्चित रूप से event का उपयोग करूंगा। यदि आप केवल एक ही क्रिया को जोड़ना चाहते हैं, तो Action या Func प्रतिनिधि का उपयोग करें।

आपके उदाहरण के लिए, Action प्रतिनिधियों में से एक को काम करना चाहिए। आपके मामले में, यह Action<string> होगा क्योंकि आपका प्रतिनिधि स्ट्रिंग तर्क लेता है। एक Action केवल एक प्रतिनिधि है जो शून्य या अधिक तर्क लेता है और शून्य लौटाता है। ऐसा लगता है कि आप कुछ भी वापस नहीं कर रहे हैं, इसलिए मैं Action का सुझाव दे रहा हूं।

यदि आप अपने प्रतिनिधि को कुछ वापस करने की आवश्यकता है तो आप केवल Func<TResult> का उपयोग करना चाहते हैं। Func और Action के बीच का अंतर यह है कि Func प्रतिनिधियों के पास वापसी का प्रकार है, और Action प्रतिनिधि नहीं हैं। इनमें से किसी भी प्रतिनिधि के पास सामान्य संस्करण हैं जो 16 या उससे अधिक तर्क ले सकते हैं।

आप एक प्रतिनिधि पर 16 से अधिक तर्क की जरूरत है आप डिजाइन :)

+1

यह उल्लेख किया जाना चाहिए कि यदि आपको पैराम्स, रेफ/आउट से कुछ अधिक जटिल की आवश्यकता है ... एक्शन/फनक काम नहीं करेगा। इसके अलावा एक और 'nicety' यह है कि आप पैरामीटर को उचित रूप से नामित कर सकते हैं (इंटेलिजेंस)। ऐसा कहा जा रहा है कि मैं एक्शन का भी उपयोग करूंगा। – Jake

1

आपका इंटरफ़ेस परिभाषा गलत है पर पुनर्विचार कर सकते हैं। आपको इसे इस तरह निर्दिष्ट करना होगा:

namespace Test 
{ 
    using System; 
    using System.Xml.Linq; 

    public interface IAction 
    { 
    DisplayMessageDelegate DisplayMessage { get; set; }; 
    void Execute(); 
    XElement Serialize(XName elementName); 
    } 

    public delegate void DisplayMessageDelegate(string message); 
} 

और फिर इंटरफ़ेस को कार्यान्वित करें।

4

आप Action<string> का उपयोग कर ऐसा कर सकते हैं।

आप Func<T> का उपयोग नहीं करना चाहते हैं, क्योंकि यह एक प्रतिनिधि को परिभाषित कर रहा है जो कोई तर्क नहीं लेता है लेकिन दूसरी तरफ टीप्रकार का एक एकल मूल्य देता है, एक प्रतिनिधि है जो टाइप टी का एक तर्क लेता है।

मैं कोशिश कर रहा सुझाव है:

public class ConsoleClass 
{ 
    public void SomeMethod() 
    { 
     ActionClass1 class1 = new ActionClass1(); 
     class1.DisplayMessage = x => Console.WriteLine(x); 
    } 
} 

या::

public class ConsoleClass 
{ 
    public void SomeMethod() 
    { 
     ActionClass1 class1 = new ActionClass1(); 
     class1.DisplayMessage = this.Print; 
    } 

    private void Print(string message) 
    { 
     Console.WriteLine(message); 
    } 
} 

आप कर सकता है

public interface IAction 
{ 
    Action<string> DisplayMessage { get; set; } 

    void Execute(); 
    XElement Serialize(XName elementName); 
} 

बार जब आप इस इंटरफेस (पूरी तरह से), आप के माध्यम से इसे इस्तेमाल कर सकते हैं लागू किया घटनाओं के साथ एक ही बात, हालांकि, मैं इस पर सवाल उठाऊंगा। आपका एपीआई एक ऐसी क्रिया का वर्णन कर रहा है जो होनी चाहिए, ऐसा कोई घटना नहीं है जो आप कर रहे हैं - और इस तरह, मैं किसी ईवेंट की अनुशंसा नहीं करता।

1

यहाँ

DisplayMessageDelegate DisplayMessage(string message); 

आप विधि है कि स्ट्रिंग स्वीकार करता है और DisplayMessageDelegate रिटर्न का वर्णन।

event DisplayMessageDelegate DisplayMessage; 

का उपयोग करें।

0

व्यक्तिगत रूप से मुझे लगता है कि आप एक अमूर्त बेस क्लास होने से सबसे अच्छा होगा, जिसने DisplayMessage नामक एक अमूर्त विधि को परिभाषित किया है और फिर उस बेस क्लास को संदेश से प्रदर्शित करने के तरीके को बदलने के लिए इसे प्राप्त करके विस्तारित किया है।

DisplayMessageDelegate DisplayMessage(string message); 

Do:

+0

मैंने इस पर विचार किया था ... मैंने इस तथ्य को छोड़ दिया (समस्या को सरल बनाने के प्रयास में) कि ये व्युत्पन्न कक्षाएं सूची संग्रह में होंगी जहां मैं प्रत्येक आइटम, सेटिंग के लिए निष्पादन विधि निष्पादित करने के लिए फ़ॉरएच लूप करता हूं उस समय के अनुप्रयोग के प्रकार के आधार पर "DisplayMessage" ऊपर ... –

0
बजाय

event Action<string> DisplayMessage; 

फिर सामान्य प्रति DisplayMessage उपयोग करते हैं, घटनाओं प्रतिनिधियों कर रहे हैं।

संबंधित मुद्दे