2012-07-03 9 views
7

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

उदा। इस तरह कुछ:

GlobalContainer 
    .RegisterFactory<ISomeObject>(
    function: ISomeObject 
    begin 
     Result := CreateComObject(CLASS_SomeObject) as ISomeObject; 
    end) 
    .Implements<ISomeObject> // could probably be implied from the above 
    .AsSingletonPerThread; 

जैसा कि आप देख सकते हैं, मेरा विशिष्ट उपयोग केस COM वस्तुओं का तात्कालिकता है। उस स्थिति में जिस इंटरफ़ेस में दिलचस्पी है, वह मेरे आवेदन का हिस्सा नहीं है, लेकिन मैं अभी भी CreateComObject/CoCreateInstance पर कॉल करके उदाहरण बनाने में सक्षम हूं। हालांकि, ऐसा लगता है कि मैं भाग्य से बाहर हूं क्योंकि कंटेनर में पंजीकरण हमेशा एक वास्तविक कार्यान्वयन वर्ग से जुड़ा हुआ प्रतीत होता है।

मान लीजिए कि इस समय इस तरह से संभव नहीं है, आप इस विशेषज्ञ को कैसे संबोधित करेंगे? क्या आप एक रैपर क्लास या डमी क्लास बनायेंगे या आप सीधे डीआई कंटेनर से COM ऑब्जेक्ट्स रखेंगे और बस उन्हें CreateComObject के माध्यम से तुरंत चालू करेंगे?

उत्तर

8

दुर्भाग्यवश वसंत डी कंटेनर का वर्तमान डिज़ाइन इसकी अनुमति नहीं देता है। यह आंतरिक रूप से मानता है कि प्रत्येक सेवा प्रकार (आमतौर पर इंटरफेस, लेकिन एक वर्ग भी हो सकता है) एक घटक प्रकार (एक वर्ग) द्वारा लागू किया जाता है। इस प्रकार TObject कई स्थानों पर जहां हमें इस मामले में IInterface की आवश्यकता होगी। प्रतिनिधि की तरह आप प्रतिनिधि को पास कर रहे हैं विधि विधि घटक प्रकार (या गैर सामान्य मामले में टॉब्जेक्ट) देता है, न कि सेवा प्रकार।

यह भी इसलिए है क्योंकि आप केवल एक धाराप्रवाह इंटरफ़ेस कॉल में एकाधिक इंटरफ़ेस कार्यान्वयन के साथ एक घटक प्रकार पंजीकृत कर सकते हैं। जैसा:

GlobalContainer 
    .RegisterType<TMyObject> 
    .Implements<IMyInterface> 
    .Implements<IMyOtherInterface>; 

कंटेनर अब की जाँच करता है, तो TMyObjectIMyInterface और IMyOtherInterface के संगत है। Resolve पर कॉल करते समय सेवा रिज़ॉल्वर अनुरोधित इंटरफ़ेस संदर्भ प्राप्त करने के लिए उदाहरण पर GetInterface का उपयोग करता है। उस बिंदु से परे सब कुछ एक वस्तु संदर्भ पर किया जाता है।

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

अद्यतन (08.11.2012):

r522 चूंकि यह इंटरफ़ेस प्रकार रजिस्टर करने के लिए निम्नलिखित तरीके से संभव है:

GlobalContainer 
    .RegisterType<ISomeObject> 
    .DelegateTo(
    function: ISomeObject 
    begin 
     Result := CreateComObject(CLASS_SomeObject) as ISomeObject; 
    end) 
    .AsSingletonPerThread; 

इस उदाहरण में यह ISomeObject सेवा और किसी भी इंटरफेस के रूप में दर्ज किए जाएंगे एक GUID के साथ यह विरासत में मिलता है।

इसके अतिरिक्त आप Implements<T> पर कॉल करके अन्य इंटरफेस जोड़ सकते हैं लेकिन कक्षाओं के विपरीत पंजीकरण समय पर कोई सत्यापन नहीं होगा यदि निर्मित उदाहरण वास्तव में वास्तव में उस इंटरफ़ेस का समर्थन करता है क्योंकि यह संभव नहीं है। वर्तमान में आपको nil मिलेगा जब Resolve<T> को गैर समर्थित सेवा प्रकार के साथ कॉल किया जाएगा। यह भविष्य में एक अपवाद उठा सकता है।

+3

अपडेट के लिए धन्यवाद! ये तो बहुत खूब है! :) –

1

वर्तमान में वसंत ढांचे के आर्किटेक्चर की तरह दिखता नहीं है लेकिन यह निश्चित रूप से व्यवहार्य है। Spring4d समर्थन समूह में यह suggested रहा है और इस विचार में रूचि है।

Spring.DesignPatterns में एक सामान्य TFactory कक्षा है जो CreateComObject/COCreateInstance लपेटने में उपयोग की जा सकती है।

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