2012-04-21 15 views
5

फ़ंक्शन से किसी ईवेंट को वापस करने के लिए वाक्यविन्यास क्या है? (घटना को कॉल करने के लिए, इसे वापस करने के लिए ताकि यह कार्य करने के लिए बाध्य हो)।फ़ंक्शन से किसी ईवेंट को लौटाना

मेरे पास एक कंटेनर क्लास है जिसमें एक शब्दकोश होता है जहां प्रत्येक सदस्यों के पास एक ईवेंट होता है।

Container c = new Container(); 
c.CreateEventForKey("a");    // Create the member in the dictionary 
c.EventForKey("a") += some_function; // Bind some_function to the event in the "a" member 
c.OnEventForKey("a","b");    // Calls some_function with argument "b" 

कंटेनर वर्ग इस तरह दिखता है:

public class Container { 

    public class Member { 
    public event Action<string> AnEvent; 
    public void OnEvent(string v) { if(AnEvent!=null) { AnEvent(v); } } 
    } 

    protected Dictionary<string,Member> members; 

    // This seems to work OK. 
    public void OnEventForKey(string k, string v) { 
    if (members.ContainsKey(k)) { members[k].OnEvent(v); } 
    else { /* report error */ } 
    } 

    // Can't get this to compile. 
    public event Action<string> EventForKey(string k) { 
    if (members.ContainsKey(k)) { return members[k].AnEvent; } 
    else { /* report error */ } 
    } 
} 

मैं कैसे EventForKey तो परिभाषित कर सकते हैं यह मैं क्या उम्मीद करता है कि

उद्देश्य कुछ इस तरह लिखने के लिए सक्षम होने के लिए है?

+1

मुझे नहीं लगता कि आप एक ईवेंट वापस कर सकते हैं, लेकिन आप एक प्रतिनिधि को वापस कर सकते हैं जो किसी ईवेंट से जुड़ा हो सकता है। क्या यही मतलब है तुम्हारा? –

+1

मुझे लगता है कि आपको ईवेंट कीवर्ड को एनेवेंट की घोषणा से, साथ ही इवेंटफोरकी के रिटर्न प्रकार से हटाने की आवश्यकता है। –

+0

@ इयान न्यूसन - मुझे जो परेशानी हो रही है उसका मुख्य हिस्सा 'c.EventForKey (" a ") + = some_function;'। मैं इसे बोझिल 'c.members [" a "] से लिखना चाहता हूं। AnEvent + = some_function', (जैसा कि मैं पहले संस्करण में त्रुटि जांच और लॉगिंग जोड़ सकता हूं, लेकिन दूसरे तक नहीं)। –

उत्तर

8

फ़ंक्शन से किसी ईवेंट को वापस करने के लिए वाक्यविन्यास क्या है?

आप आसानी से नहीं कर सकते हैं। घटनाक्रम - गुणों की तरह - वास्तव में पहले वर्ग "वस्तुएं" जैसी नहीं हैं; वे एक वर्ग के सदस्य हैं। आप वास्तव में में एक क्लास सदस्य नहीं हैं - आप केवल एक शब्दकोश में प्रतिनिधियों को रखने की कोशिश कर रहे हैं।

आप अपना खुद का "ईवेंट-जैसे" कंटेनर बना सकते हैं, लेकिन वैकल्पिक डिजाइनों पर विचार करना शायद बेहतर है, उदाहरण के लिए

c.Subscribe("a", SomeFunction); 
c.OnEventForKey("a"); 

आप प्रेरणा के लिए EventHandlerList पर देखना चाह सकते हैं।

0

क्यों न केवल सदस्य लौटाएं और इसकी घटना की सदस्यता लें?

public IMember MemberForKey(string key) // return IMember 
{ 
    if (!members.ContainsKey(key)) 
     throw new Exception(); 

    return members[key]; 
} 

और फिर सदस्यता ली है:

Container c = new Container(); 
c.CreateEventForKey("a");    
c.MemberForKey("a").AnEvent += some_function; 
c.OnEventForKey("a", "b"); 

लेकिन आप Member कक्षा में सार्वजनिक OnEvent विधि है। क्लाइंट द्वारा घटनाओं को बढ़ाने के लिए, आप इंटरफ़ेस बना सकते हैं जो केवल ईवेंट दिखाएगा। बस Member वर्ग द्वारा इस इंटरफ़ेस को लागू:,

public interface IMember 
{ 
    event Action<string> AnEvent; 
} 

और हाँ, आप वापस नहीं लौट सकते घटना, क्योंकि वास्तव में घटना आपत्ति नहीं है, यह दो तरीकों add और remove, जो प्रतिनिधि के भीतरी क्षेत्र के लिए जोड़ सकते हैं और प्रतिनिधियों को दूर के लिए निर्धारित है प्रकार। यहां अपने घटना की तरह लग रहा है:

private Action<string> _action; // field of delegate type 

    public event Action<string> AnEvent 
    { 
     add { _action += value; } 
     remove { _action -= value; } 
    } 

घटना का उद्देश्य ग्राहकों के लिए केवल दो आपरेशन प्रदान करना है - जोड़ने और हैंडलर निकाल। प्रतिनिधि खुद को ग्राहकों के लिए छिपा हुआ है। आप इसे सार्वजनिक कर सकते हैं:

public Action<string> _action; 

लेकिन इस मामले में कोई भी ग्राहक इसे आमंत्रित कर सकता है।

अद्यतन: यदि आप/सदस्यता लें के साथ जाने के वाक्य रचना निकालना चाहते हैं, तो बस संचालकों के साथ शब्दकोश का उपयोग करें:

public class Container 
{ 
    private Dictionary<string, Action<string>> handlers = 
      new Dictionary<string, Action<string>>(); 

    public void CreateEventForKey(string key) 
    { 
     // with empty handler added you can avoid null check 
     handlers.Add(key, (value) => { }); 
    } 

    public void OnEventForKey(string key, string value) 
    { 
     if (!handlers.ContainsKey(key)) 
      throw new Exception(); 

     handlers[key](value); 
    } 

    public void Subscribe(string key, Action<string> handler) 
    { 
     if (!handlers.ContainsKey(key)) 
      throw new Exception(); 

     handlers[key] += handler; 
    } 
} 
0
यहाँ

पूरा काम कर उदाहरण है:

class Program 
{ 
    static void Main(string[] args) 
    { 
     Container c = new Container(); 
     c.CreateEventForKey("a");    // Create the member in the dictionary 
     c.EventForKey("a").Add(str => Console.WriteLine(str)); 
     c.EventForKey("a").Add(str => Console.WriteLine(str.ToUpper())); 
     c.OnEventForKey("a", "baa baa black sheep"); 

     Console.ReadLine(); 
     } 
    } 

    public class Container 
    { 

     public class Member 
     { 
     public List<Action<string>> AnEvent = new List<Action<string>>(); 
     public void OnEvent(string v) 
     { 
      if (AnEvent != null) 
      { 
       this.AnEvent.ForEach(action => action(v)); 
      } 
     } 

     public void AddEvent(Action<string> action) 
     { 
      this.AnEvent.Add(action); 
     } 
    } 

    protected Dictionary<string, Member> members = new Dictionary<string,Member>(); 

    public void CreateEventForKey(string key) 
    { 
     this.members[key] = new Member(); 
    } 

    // This seems to work OK. 
    public void OnEventForKey(string k, string v) 
    { 
     if (members.ContainsKey(k)) { members[k].OnEvent(v); } 
     else { /* report error */ } 
    } 

    public List<Action<string>> EventForKey(string k) 
    { 
     if (members.ContainsKey(k)) { return members[k].AnEvent; } 
     else { throw new KeyNotFoundException(); } 
    } 
} 

अंतर करने के लिए इसी तरह व्यवहार करने के लिए है प्रतिनिधियों की एक सूची का उपयोग करके एक घटना।

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