2008-10-29 12 views
11

समस्या बहुत सरल है। किसी ऑब्जेक्ट को कुछ घटनाओं को सूचित करने की आवश्यकता होती है जो पर्यवेक्षकों के लिए रूचि हो सकती हैं।रूबी में .NET घटनाओं के बराबर क्या है?

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

// Object with events 
public delegate void HandlerSignature(int a); 
public event HandlerSignature MyEvent; 
public event HandlerSignature AnotherCriticalEvent; 

// Client 
MyObject.MyEvent += new HandlerSignature(MyHandlerMethod); // MyHandlerMethod has same signature as delegate 

क्या कोई EventDispatcher मॉड्यूल या कुछ ऐसा है जो मुझे याद आ रहा है कि मैं रूबी क्लास पर जा सकता हूं? रुबी के सिद्धांत के साथ कम से कम आश्चर्य के साथ खेलने वाले एक उत्तर की उम्मीद है। एक घटना घटना का नाम होगा [पर्यवेक्षक, विधि नाम] वस्तुओं की कतार जो ईवेंट होने पर लागू होने की आवश्यकता होती है।

उत्तर

2
+1

बिल्कुल नहीं .. यह पर्यवेक्षक डिजाइन पैटर्न का कार्यान्वयन प्रतीत होता है। मुझे बॉयलर ऑब्जेक्ट के लिए वॉटरएक्स्टेड, स्टार्ट इत्यादि जैसे कई कार्यक्रमों का पर्दाफाश करने और थियेटर हैंडलर (एक एकल 'अपडेट' विधि से बाध्य नहीं) के लिए सदस्यता लेने वाले ग्राहकों को – Gishu

8

सबसे पहले, रूबी में कोई विधि हस्ताक्षर कर रहे हैं। निकटतम कार्य की धैर्य की जांच करेगा। बतख टाइपिंग को अलग-अलग सोचने की आवश्यकता होती है (थोड़ा)।

नमूदार मॉड्यूल एक शुरुआत है, लेकिन यह पर्याप्त नहीं हो सकता है यदि आप एक ही वर्ग से आने वाले अनेक घटनाओं के लिए एक आवश्यकता है।

यह एक त्वरित स्केच है। यह विधियों और ब्लॉक का समर्थन करता है। अपने कोड, थ्रेडिंग दृष्टिकोण इत्यादि के अनुकूल होने के लिए आवश्यक के रूप में संशोधित करें। उदाहरण के लिए, आप पैरामीटर के रूप में विधि नाम में ईवेंट नाम रखने के लिए method_missing का उपयोग कर सकते हैं।

class EventBase 
    def initialize 
     @listeners = Hash.new 
    end 

    def listen_event(name, *func, &p) 
     if p 
      (@listeners[name] ||= Array.new) << p 
     else 
      (@listeners[name] ||= Array.new) << func[0] 
     end 
    end 

    def ignore_event(name, func) 
     return if [email protected]_key?(name) 
     @listeners[name].delete_if { |o| o == func } 
    end 

    def trigger_event(name, *args) 
     return if [email protected]_key?(name) 
     @listeners[name].each { |f| f.call(*args) } 
    end 
end 


class MyClass < EventBase 
    def raise_event1(*args) 
     trigger_event(:event1, *args) 
    end 

    def raise_event2(*args) 
     trigger_event(:event2, *args) 
    end 
end 

class TestListener 
    def initialize(source) 
     source.listen_event(:event1, method(:event1_arrival)) 
     source.listen_event(:event2) do |*a| 
      puts "event 2 arrival, args #{a}" 
     end 
    end 

    def event1_arrival(*a) 
     puts "Event 1 arrived, args #{a}" 
    end 
end 

s = MyClass.new 
l = TestListener.new(s) 

s.raise_event1("here is event 1") 
s.raise_event2("here is event 2") 
2

मैं गूंजता हूं कि रूबी में .NET ईवेंट में भाषा-स्तर एनालॉग नहीं है। रेलवे जिस तरह से संबंधित है, वह ActiveSupport::Callbacks के साथ है (उस पृष्ठ पर एक उदाहरण है)।

+0

संभवतः क्योंकि रूबी एक भाषा है, ढांचा नहीं है? –

+0

यदि मैं इसे समझता हूं .. रेल में कॉलबैक हुक की तरह अधिक हैं .. जहां आपको एक निश्चित बिंदु पर एक कक्षा से प्लग-इन व्यवहार करने के लिए प्राप्त करना है। काफी घटनाएं नहीं .. जो 'पर्यवेक्षक' और 'देखने योग्य' जोड़े को नहीं जोड़ती – Gishu

6

क्यों अपनी खुद की घटना वर्ग नहीं लिख?

class Event 
    def initialize 
    @handlers = Array.new 
    end 

    def fire 
    @handlers.each do |v| 
     v.call 
    end 
    end 

    def << handler 
    @handlers << handler 
    end 
end 

e = Event.new 

e << lambda { puts "hello" } 
e << lambda { puts "test" } 
e.fire 

यह केवल एक न्यूनतम नमूना है, लेकिन इसे किसी भी तरीके से बढ़ाया जा सकता है। और इस तरह मापदंडों EventArgs नेट में जोड़ें, या जो भी आप ;-)

0

चाहते क्योंकि मैं बिल्कुल वैसा ही मुद्दा था मैं सिर्फ इस बात के लिए एक रत्न लिखा था। इस प्रयास करें:

gem install ruby_events 

पर http://github.com/nathankleyn/ruby_events के रूप में निर्देशों का पालन करें, लेकिन संक्षेप में:

require 'rubygems' 
require 'ruby_events' 

class Example 
    def initialize 
    events.listen(:test_event) do |event_data| 
     puts 'Hai there!' 
     puts event_data 
    end 
    end 

    def call_me 
    events.fire(:test_event, 'My name is Mr Test Man!') 
    end 
end 

e = Example.new 
e.call_me # Fires the event, and our handler gets called! 
0

इस पर एक त्वरित टिप्पणी। मेरा सुझाव है कि आप EventMachine

यह एक अलग एक ही विचार देखने को देखो। यह एक ईवेंट संचालित प्रतिमान लागू करता है ताकि आप नेट घटनाओं के बराबर एक-स्तर ऊपर हों और EventMachine मॉड्यूल को सीएलआर ईवेंट हैंडलर के रूप में मानें।

इसके अलावा एक कदम पीछे लेना, रूबी एक स्मॉलटाक प्रसंस्करण मॉडल का पालन करता है जहां किसी विधि को कोई कॉल ऑब्जेक्ट पर भेजा गया संदेश (जैसा कि एक ईवेंट है) (भेजें() विधि देखें)। EventMachine आपको घटनाओं पर एक एकल थ्रेडेड टुकड़ा देता है।आप थ्रेड या श्रमिकों को संभालने के लिए रैक जैसे कुछ का उपयोग कर सकते हैं।

1

विभिन्न ruby state machine libraries पर एक नज़र डालें। वे सिर्फ घटनाओं की तुलना में एक बड़ी समस्या को हल करने का इरादा रखते हैं, लेकिन आपको समाधान प्रदान कर सकते हैं।

मैंने सफलता के साथ state_machine मणि का उपयोग किया है, जिसमें events शामिल है।

0

मैं एक नोब हूं लेकिन रुबी वास्तव में शक्तिशाली लगता है। आप सी # शैली घटनाओं अपने आप को इस तरह लागू कर सकते हैं:

module Observable 
    class Event 
     def initialize 
      @to_call = [] 
     end 
     def fire(*arguments) 
      @to_call.each { |proc| proc.call(*arguments) } 
     end 
     def call(proc) 
      @to_call << proc 
     end 
     def dont_call(proc) 
      @to_call.delete proc 
     end 
    end 
    def self.append_features(cls) 
     def cls.event(sym) 
      define_method(sym.to_s) do 
       variable_name = "@#{sym}" 
       if not instance_variable_defined? variable_name then 
        instance_variable_set variable_name, Event.new 
       end 
       instance_variable_get variable_name 
      end 
     end 
    end 
end 

# Example 

class Actor 
    include Observable 
    event :whenActed 
    def act 
     whenActed.fire("Johnny") # fire event whenActed with parameter Johnny 
    end 
end 

actor = Actor.new 

def apploud(whom) 
    print "Bravo #{whom}!\n" 
end 

applouder = method(:apploud) 

actor.whenActed.call applouder 

actor.act 
0

मैं एक मणि वास्तव में कर रही है तुम क्या चाहते बनाया है और आश्चर्यजनक रूप से event_dispatcher कहा जाता है के रूप में आप का उल्लेख किया। मुझे आशा है कि यह किसी की मदद करेगा: event_dispatcher

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