2010-02-04 6 views
12

मान लें, हम एक वर्ग है:किसी विधि के लिए IObservable बनाने का एक अच्छा तरीका क्या है?

public class Foo 
{ 
    public string Do(int param) 
    { 
    } 
} 

मैं मानों द्वारा उत्पादित किया जा रहा है विधि करो का एक नमूदार बनाना चाहते हैं। ऐसा करने का एक तरीका यह होगा कि से पर कॉल किया जा रहा है और पर्यवेक्षण योग्य उपयोग करें। से देखने योग्य बनाने के लिए उपयोग करें। लेकिन किसी भी तरह से मैं सिर्फ कार्य के लिए एक घटना के निर्माण के बारे में अच्छा महसूस नहीं करता हूं। इसे करने का कोई बेहतर तरीका है?

उत्तर

5

मैट का जवाब मुझे इस बारे में सोच कर दिया। नमूना कोड के साथ एक अच्छा लेख है जो स्ट्रक्चर मैप के साथ कार्यान्वयन दिखाता है।

http://www.codeproject.com/KB/architecture/event_aggregator.aspx

+1

यदि आप वास्तव में इसके लिए देख रहे हैं, तो आपको कम से कम एक पंक्ति को सार्वजनिक IObservable DoValues ​​{get {return _doValues.AsObservable में बदलकर अपनी आंतरिक स्थिति की रक्षा करनी चाहिए(); }}। इससे उपभोक्ताओं को रोका जा सकता है, बस अपने IObservable को एक ISubject और OnNext- को अपने स्वयं के मानों में डालना होगा। :( –

1

मुझे लगता है कि आप फू क्लास को नियंत्रित करते हैं, क्योंकि आप इसे एक विकल्प के रूप में एक ईवेंट जोड़ने के बारे में बात कर रहे हैं। चूंकि आप कक्षा के मालिक हैं, क्या कोई कारण है कि आप अपनी विधि के लिए अपने स्वयं के IObservable कार्यान्वयन को परिभाषित नहीं कर सकते हैं?

public class Foo 
{ 
    DoObservable _doValues = new DoObservable(); 

    public IObservable<String> DoValues 
    { 
     return _doValues; 
    } 

    public string Do(int param) 
    { 
     string result; 
     // whatever 
     _doValues.Notify(result); 
    } 
} 

public class DoObservable : IObservable<String> 
{ 
    List<IObserver<String>> _observers = new List<IObserver<String>>(); 

    public void Notify(string s) 
    { 
     foreach (var obs in _observers) obs.OnNext(s); 
    } 

    public IObserver<String> Subscribe(IObserver<String> observer) 
    { 
     _observers.Add(observer); 
     return observer; 
    } 
} 

आपका वर्ग अब एक Observable<String> संपत्ति जो एक तरह से मान Do विधि से लौटे की सदस्यता के लिए प्रदान करता है:

public class StringWriter : IObserver<String> 
{ 
    public void OnNext(string value) 
    { 
     Console.WriteLine("Do returned " + value); 
    } 

    // and the other IObserver<String> methods 
} 

var subscriber = myFooInstance.DoValues.Subscribe(new StringWriter()); 
// from now on, anytime myFooInstance.Do() is called, the value it 
// returns will be written to the console by the StringWriter observer. 

मैं प्रतिक्रियाशील ढांचे में बहुत ज्यादा हाथ आजमाया नहीं गया है, लेकिन मैं लगता है कि यह इस बात के करीब है कि आप यह कैसे करेंगे।

public class Foo 
{ 
    private readonly Subject<string> _doValues = new Subject<string>(); 

    public IObservable<string> DoValues { get { return _doValues; } } 

    public string Do(int param) 
    { 
     var ret = (param * 2).ToString(); 
     _doValues.OnNext(ret); 
     return ret; 
    } 
} 


var foo = new Foo(); 
foo.DoValues.Subscribe(Console.WriteLine); 
foo.Do(2); 
+0

आप अपने DoObserver कक्षा को फू क्लास की एक आंतरिक (नेस्टेड) ​​कक्षा भी बना सकते हैं, इसे बंद सिस्टम के रूप में रखने के लिए भी। –

+0

यह भी देखें कि http://stackoverflow.com/questions/1768974/implementing-iobservablet-from-scratch, जिसमें IDISposable के माध्यम से सदस्यता रद्द करने का समर्थन करने सहित एक पूर्ण कार्यान्वयन है। –

+0

आपका DoObservable केवल विषय है, पहिया को फिर से शुरू करने की कोई आवश्यकता नहीं है –

-2

मैं EventAggregator मॉडल पर दिखेगा:

+0

मेरा प्रश्न विशेष रूप से आरएक्स एक्सटेंशन का उपयोग करके कार्य को सबसे कुशलता से पूरा करने के तरीके पर था। आपके द्वारा प्रदान किया गया लिंक आरएक्स से संबंधित नहीं है। –

+0

यहां भ्रम के लिए खेद है, लेकिन सवाल यह है कि "एक विधि के लिए IObservable बनाने का एक अच्छा तरीका क्या है?"। आरएक्स एक्सटेंशन के बारे में कुछ कहां कहता है? EventAggregator पर्यवेक्षक पैटर्न को प्राप्त करने का एक decoupled रूप है। अभी भी मेरी राय में एक नजर लायक है। –

+0

एक संदर्भ है जो आरएक्स को इंगित करता है - टैग, Observable.FromEvent का उपयोग करने के मौजूदा समाधान का संदर्भ। वैसे भी, अब से केवल "असली" IObservable एक सिस्टम से आता है। प्रतिक्रियाशील नामस्थान। –

1

आम तौर पर आप विषयों का उपयोग कर से बचने के लिए चाहते हैं। मेरे प्रयोग में यह एक संकेत है कि आप कुछ गलत कर रहे हैं। अवलोकन योग्य। बनाना या शायद उत्पन्न करना सामान्य रूप से बेहतर फिट बैठता है।

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

+0

में बनाया गया है, मैं असहमत हूं, अवलोकन करता हूं। क्रेट आरएक्स सेमेटिक्स को लागू नहीं करता है, आपको इसे स्वयं करना है - यदि यह कम है तो भी विषय का उपयोग करना आसान है कार्यात्मक रूप से सही ™। जब आपको इसकी ज़रूरत होती है तो बनाएं, लेकिन यह अक्सर अधिक हो जाता है। –

+1

विषय आरएक्स द्वारा प्रदान की गई कार्यात्मक और ऑब्जेक्ट उन्मुख दुनिया के बीच एक "पुल" है। इसलिए जब तक आपका कोड 100% कार्यात्मक न हो, विषय काफी उपयोगी होते हैं। –

+0

असहमत सहमत हैं। स्मार्ट लोगों के समूह के साथ एक वाणिज्यिक परियोजना पर 2 साल के लिए आरएक्स का उपयोग करने के बाद हम सभी इस निष्कर्ष पर पहुंचे कि विषय कोड गंध हैं, हमेशा गलत नहीं, बल्कि आम तौर पर कोड समीक्षा में चर्चा का एक बिंदु है। यह भी एक शर्म की बात है कि लोग @ सर्गी को प्रोत्साहित कर रहे हैं और अपने कोड के साथ समस्याओं को इंगित नहीं कर रहे हैं (विशेष रूप से। ऑब्सर्वेबल())। केवल मदद करने की कोशिश कर रहा है। –

0

अवलोकन योग्य। जनरेट आपकी समस्या हल करता है, हालांकि आपको स्थिति का उपयोग करने और अपने नमूने के लिए जारी रखने की आवश्यकता नहीं है। यह सिर्फ बनाता है और वस्तु और लगातार छदाम() करने के लिए कॉल के परिणाम देता है:

Observable.Generate (
    new Foo(), 
    item => true, // in your example, this never terminates 
    item => item, // we don't actually do any state transitions 
    item => { return item.DoIt(); } // This is where we emit our value 
); 

अभ्यास में, आप अक्सर कुछ राज्य पर नज़र रखने और कुछ समाप्ति हालत करना चाहते हैं। उत्पन्न करना आसान बनाता है।

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