मन में COM सीमाओं के साथ अपने .NET पुस्तकालय को लिखने के लिए बेहतर है, या अपने .NET पुस्तकालय को इंटरोप से अलग करें?


9

मुझे यह दिलचस्प लेख आया : मैं कोडप्रोजेक्ट पर कॉम कॉम इंटरऑपरेबिलिटी से कैसे प्यार हुआ , जो मुझे सोच में पड़ गया ...

लेखक का तर्क है कि वे अपने .NET पुस्तकालय में कोई COM-ities नहीं चाहते हैं क्योंकि यह उनके .NET पुस्तकालय की सुंदरता से दूर ले जाता है। इसके बजाय, वे बल्कि एक अलग इंटरॉप लाइब्रेरी लिखेंगे जो उनके .NET लाइब्रेरी को COM में उजागर करता है। यह इंटरोप लाइब्रेरी इस तथ्य को संभालेगी कि COM कंस्ट्रक्टर्स को पैरामीटर्स, ओवरलोडेड मेथड, जेनरिक, इनहेरिटेंस, स्टेटिक मेथड्स आदि का समर्थन नहीं करता है।

और जब मुझे लगता है कि यह बहुत उपन्यास है, तो क्या यह परियोजना को संकलित नहीं करता है?

  • अब आपको अपने .NET लाइब्रेरी और एक इंटरॉप लाइब्रेरी को यूनिट टेस्ट करने की आवश्यकता है।
  • अब आपको अपने सुंदर .NET पुस्तकालय के आसपास काम करने के तरीके का पता लगाने और उसे COM में उजागर करने के लिए समय बिताने की आवश्यकता है।
  • आपको अपनी कक्षा की गिनती को प्रभावी ढंग से दोगुना या तिगुना करने की आवश्यकता है।

मैं निश्चित रूप से समझ सकता हूं कि क्या आपको COM और गैर-COM दोनों का समर्थन करने के लिए अपने पुस्तकालय की आवश्यकता है। हालाँकि, यदि आप केवल COM का उपयोग करने का इरादा रखते हैं तो क्या इस तरह का डिज़ाइन कोई लाभ लाता है जो मुझे नहीं दिखता है? क्या आप केवल C # भाषा का लाभ प्राप्त करते हैं?

या, क्या यह आपको एक रैपर प्रदान करके आपके पुस्तकालय को आसान बनाता है? क्या COM के उपयोग की आवश्यकता नहीं होने से यह आपके यूनिट टेस्ट को तेजी से चलाता है?


2
आपका मतलब है, असली कोड को बेहतर / क्लीनर बनाने के लिए उपयोगी उपकरणों का उपयोग करने में सक्षम होने के अलावा? और उस (संभवतः विरासत) COM सामान के लिए एक स्पष्ट प्रवास पथ प्रदान करना?
तेलस्टिन

3
यह पूरे नाम स्थान पर एक बड़े पैटर्न रिट की तरह है। मुझे लगता है कि इसे इस तरह व्यवस्थित करना स्मार्ट है यदि आप .NET सुविधाओं का उपयोग करना चाहते हैं लेकिन वास्तव में OLE स्वचालन की आवश्यकता है। आपके COM रैपर मूल रूप से आधुनिक (अपरिवर्तनीय? जेनरिक?) मुहावरों को पैरामीटर रहित कन्स्ट्रक्टरों, भारी उत्परिवर्तनीय वस्तुओं और अपनी सामान्य सूचियों के लिए SAFEARRAYs में बदलने के लिए होंगे। यदि आप अन्य .NET घटकों का समर्थन कर रहे हैं या पूरी तरह से नई शैलियों के साथ प्यार में हैं तो यह समझ में आएगा। यदि आप केवल COM का समर्थन कर रहे हैं, तो VB6 (32 बिट) में पूरी बात क्यों न लिखें और केवल एक मुहावरा रखें?
माइक

3
@MasonWheeler: यह उसी तरह से चित्रित किया गया है जैसे 6 महीने से पुराने सभी सॉफ्टवेयर "विरासत" है, क्या मैं सही हूं?
whatsisname

2
@MasonWheeler COM को कोई फर्क नहीं पड़ता है कि कितने लोग (Microsoft के भीतर कुछ समूहों सहित) इसे पसंद करेंगे, क्योंकि यह अभी भी आउट-ऑफ-प्रोसेस चीजों को नियंत्रित करने का सबसे अच्छा विकल्प है।
माइक

2
@ माय, मैं वास्तव में C # .NET को VB6 प्रोजेक्ट पोर्ट कर रहा हूँ। हमारे द्वारा उपयोग किए जाने वाले उपयोगकर्ता का सामना करने वाले एपीआई बहुत सरल हैं, हालांकि, पर्दे के पीछे का कोड यथायोग्य नहीं है। मैं C # .NET में अधिकांश लाइब्रेरी को कार्यान्वित करने की उम्मीद कर रहा हूं और एक इंटरोप फेकड प्रदान करता हूं जो विभिन्न वर्गों के साथ बातचीत करने वाले सरल एपीआई प्रदान करता है।

जवाबों:


7

हालाँकि, यदि आप केवल COM का उपयोग करने का इरादा रखते हैं तो क्या इस तरह का डिज़ाइन कोई लाभ लाता है जो मुझे नहीं दिखता है?

अपने प्रश्न का यह टुकड़ा है यहाँ डिज़ाइन निर्णय का सबसे महत्वपूर्ण हिस्सा है, और जवाब (हमेशा की तरह) है यह निर्भर करता है

यदि आप केवल COM इंटरॉप के माध्यम से पुस्तकालय का उपयोग करने का इरादा रखते हैं, तो आपको इसे ध्यान में रखते हुए पूरे सिस्टम को डिजाइन करना चाहिए। लाइन की गिनती को तिगुना करने का कोई कारण नहीं है। प्रणाली में जितना अधिक LoC होगा, उतने ही अधिक दोष होंगे। इसलिए आपको अपने सिस्टम को केवल COM संगत कार्यक्षमता का उपयोग करने के लिए डिज़ाइन करना चाहिए।

हालाँकि , मैं .Net पुस्तकालय के उपयोग को COM तक सीमित करने के लिए एक अच्छा कारण नहीं सोच सकता। आप अन्य .Net कोड में असेंबली का उपयोग क्यों नहीं कर पाएंगे? यह अपने आप को इस तरह सीमित करने के लिए बहुत कम समझ में आता है।

मुझे इसके साथ कुछ अनुभव है, इसलिए मैं इसे साझा करूंगा कि मैंने इसे कैसे संभाला है। इसका निश्चित रूप से आदर्श नहीं है। मैंने कुछ ट्रेड ऑफ किए हैं। मैं केवल COM वर्गों (वास्तव में इंटरफेस) के लिए एक मुखौटा का उपयोग करता हूं जो नए .Net मुहावरों के साथ असंगत हैं, अन्यथा, मैं सीधे COM के लिए .Net इंटरफ़ेस को उजागर करता हूं। यह मूल रूप से इसका मतलब है कि मैं जेनरिक का उपयोग करने वाले किसी भी इंटरफ़ेस के लिए एक मुखौटा का उपयोग करता हूं। जेनरिक केवल एक चीज है जो मैं भर में आया हूं वह सिर्फ असंगत है। दुर्भाग्य से, इसका मतलब है कि किसी भी चीज़ के लिए एक मुखौटा IEnumerable<T>जो एक रिटर्न देता है , जो काफी सामान्य है।

हालाँकि, यह लगभग उतना बुरा नहीं है जितना यह प्रतीत होता है, क्योंकि आपका मुखौटा वर्ग आपके .Net वर्ग से विरासत में मिलता है और एक विशिष्ट इंटरॉप इंटरफ़ेस को लागू करता है। कुछ इस तरह।

namespace Company.Product.Feature
{
    public class MyClass : INetInterface 
    {
        // lots of code
    }
}

namespace Company.Product.Interop
{
    public class MyClass : Feature.MyClass, IComInterface
    {
        // over ride only the  incompatible properties/methods
    }
}

यह आपके डुप्लिकेट कोड को पूर्णतम रखता है और आपके COM इंटरफ़ेस को "अनजाने" परिवर्तनों से बचाता है। जैसे ही आपका कोर क्लास / इंटरफ़ेस बदलता है, आपके एडेप्टर क्लास को अधिक तरीकों की सवारी करना पड़ता है (या इंटरफ़ेस को तोड़ना और प्रमुख संस्करण संख्या को टक्कर देना)। दूसरी ओर, आपके सभी इंटरोप कोड Interopनामस्थान में संग्रहीत नहीं हैं , जिससे एक भ्रमित फ़ाइल संगठन हो सकता है। जैसा मैंने कहा, यह एक व्यापार बंद है।

इसके पूर्ण विकसित उदाहरण के लिए, आप मेरे रेपो के SourceControl और Interop फ़ोल्डर के माध्यम से ब्राउज़ कर सकते हैं । ISourceControlProviderऔर GitProviderविशेष रुचि होगी।


प्रतिक्रिया के लिए धन्यवाद @ RubberDuck! मैं कुछ दिन पहले रबरडक परियोजना में भाग गया था; यह कोड के माध्यम से बहुत ही रोचक ढंग से पढ़ा गया है। क्या आप IEnumerableवीबीए पास करने में सक्षम हैं ? इसके अलावा, Rubberduck.Interop.GitProviderयदि आप COM का समर्थन नहीं करते हैं , तो आप पैरामीटर किए गए निर्माणकर्ताओं को क्यों परिभाषित करते हैं?
रोबोडुडे666

हां, आप IEnumerableCOM से गुजर सकते हैं , लेकिन इसका पुराना, गैर-सामान्य संस्करण होना चाहिए। के रूप में निर्माणकर्ताओं के लिए, पर एक नज़र रखना SourceControlClassFactory। मूल रूप से, आप इसे एक ऐसे वर्ग के उदाहरण से जोड़कर नकली बनाते हैं, जिसे इसके ctor के लिए मापदंडों की आवश्यकता नहीं होती है और यह आपके API की कक्षाओं के नए उदाहरणों तक पहुँच प्राप्त करने के लिए उपयोग करता है।
रबरडक

मैं अनुमान लगा रहा हूँ कि आपके ComVisible(true)वर्ग / इंटरफेस में परिभाषित कुछ भी जो COM का समर्थन नहीं करता है, उसे केवल "अनदेखा" किया जाता है? यदि आप एक से अधिक नाम ProgIdउजागर करना चाहते हैं तो आपको कई नामस्थानों में परिभाषित एक ही नाम का एक वर्ग है, तो आप यह भी अनुमान लगा सकते हैं कि क्या आपको एक अद्वितीय प्रदान करना होगा?
रोबोडुडे666

हाँ। यह सही है और staticतरीकों की अनदेखी की जाती है। मैं यह देखने की कोशिश कर रहा हूं कि क्या VB6 के VB_PredeclaredIdउपलब्ध होने के बराबर है। मैं सोच रहा हूं कि एक डिफ़ॉल्ट उदाहरण बनाना संभव हो सकता है।
रबरडक

7

यह उनके .NET पुस्तकालय की सुंदरता से दूर ले जाता है

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

कॉम के रूप में अपनी कक्षाओं को चिह्नित करने में सक्षम होना और COM के माध्यम से अपने .NET कोड से बात करने में सक्षम होना काफी उपयोगी है। सुंदरता के लिए उत्पादकता के लिए महान लाभ को समझना पागल है।

हालाँकि, COM के साथ काम करने के लिए कुछ ट्रेड-ऑफ की आवश्यकता होती है, इसके लिए एक नॉन-आर्ग कंस्ट्रक्टर की आवश्यकता होती है, और उनमें से कुछ अन्य सामान का आपने उल्लेख किया है। यदि वे सुविधाएँ हैं जो आप वैसे भी उपयोग नहीं कर रहे हैं, या यह आपको उनका उपयोग नहीं करने के लिए चोट नहीं पहुँचाएगा, तो कॉम और गैर कॉम के लिए एक ही कक्षा का उपयोग करके सहेजने के लिए बहुत सारे काम हैं।

दूसरी ओर, यदि आपके COM क्लाइंट नाटकीय रूप से भिन्न इंटरफ़ेस की अपेक्षा करते हैं, तो निर्भरताएँ या अन्य सीमाएँ हैं जो आपके .NET क्लासेस से निपटने के लिए खराब हैं, या आप अपने .NET क्लासेस को महत्वपूर्ण रूप से बदलते रहने की उम्मीद करते हैं और COM को पिछड़े बनाए रखने की आवश्यकता है- अनुकूलता, तो हर तरह से उस अंतर को पाटने के लिए एक इंटरॉप क्लास बना सकते हैं।

लेकिन "सौंदर्य" के बारे में मत सोचो। .NET के माध्यम से COM को उजागर करने में सक्षम होने का मतलब है कि आप काम को बचा सकते हैं। अपने लिए और काम न बनाएं।


+1। जब भी मुझे ब्लैक बॉक्स पर काले बटन की सुंदरता पसंद आती है, व्यावहारिक रूप से अधिक महत्वपूर्ण होते हैं।
gbjbaanb

दरअसल, इस चर्चा में "सौन्दर्य" शब्द का परिचय देने वाले व्यक्ति को वेक-अप-थप्पड़ की आवश्यकता हो सकती है, और यह उस अन्य लेख का लेखक नहीं था।
डॉक ब्राउन

2
बस एक पक्ष ध्यान दें, यदि आपके वर्तमान कंस्ट्रक्टरों को args की आवश्यकता है, तो यह आपके COM घटकों के लिए मौजूदा इंटरफ़ेस / API को फिर से डिज़ाइन करने के बजाय एक क्लास फैक्ट्री प्रदान करना सबसे अच्छा है।
रबरडक

1
क्या आपके कारखाने को "GlobalMultiUse" वर्ग के रूप में उजागर करना संभव है? तो आप बस Set oObject = MyCOMInterop.NewMyClass()एक नई फैक्टरी वस्तु को पहले पलटने के बिना कर सकते हैं ?
रोबोडुडे666

यह एक अच्छा सवाल है @ robodude666। अब जब आप इसका उल्लेख करते हैं, तो मुझे आशा है कि
रबरडक

3

ठीक है, निष्पक्ष होने के लिए, उस लेख के मूल लेखक ने अपने लेख में कहीं भी "सौंदर्य" शब्द का उपयोग नहीं किया, वह आप थे, जो उस पर एक पक्षपाती प्रभाव दे सकते हैं, जिन्होंने उस लेख को पढ़ने के लिए समय नहीं लिया था खुद को।

जहाँ तक मैंने उस लेख को समझा है, .NET पुस्तकालय पहले से ही मौजूद था और COM को ध्यान में रखे बिना लिखा गया था - शायद इसलिए कि जब पुस्तकालय बनाया गया था, उस समय COM का समर्थन करने की कोई आवश्यकता नहीं थी।

बाद में, COM का समर्थन करने की अतिरिक्त आवश्यकता शुरू की गई थी। ऐसी स्थिति का सामना करना, आपके पास दो विकल्प हैं:

  • COM इंटरॉप को संगत बनाने के लिए मूल काम को फिर से डिज़ाइन करें (चीजों को तोड़ने के जोखिम के साथ)

  • मूल वर्किंग लाइब्रेरी को ज्यादातर वैसे ही रहने दें, और इसके बजाय एक "रैपर" (या "एडाप्टर") के फ़ंक्शन के साथ एक अलग असेंबली बनाएं

रैपर या एडेप्टर बनाना एक जाना-माना डिज़ाइन पैटर्न है (या इस मामले में अधिक वास्तु पैटर्न), और पेशेवरों और विपक्षों को भी अच्छी तरह से जाना जाता है। इसके लिए एक तर्क बेहतर है "चिंताओं को अलग करना", और इसका सुंदरता से कोई लेना-देना नहीं है।

अपनी चिंताओं के लिए

अब आपको अपने .NET लाइब्रेरी और एक इंटरॉप लाइब्रेरी को यूनिट टेस्ट करने की आवश्यकता है।

जब आप अपने COM इंटरफ़ेस को अपने मौजूदा .NET लाइब्रेरी में रीडिज़ाइन द्वारा पेश करते हैं, तो आपको उस इंटरफ़ेस का परीक्षण करना होगा। मैन्युअल रूप से लिखे गए एडॉप्टर को प्रस्तुत करने के लिए कुछ अतिरिक्त परीक्षणों की आवश्यकता हो सकती है जो इंटरफ़ेस काम कर रहे हैं, लेकिन यह आवश्यक नहीं है कि लिब के मुख्य व्यवसाय की कार्यक्षमता के सभी यूनिट परीक्षणों को कॉपी किया जाए। यह मत भूलो कि यह केवल एक और इंटरफ़ेस है।

अब आपको अपने सुंदर .NET पुस्तकालय के आसपास काम करने के तरीके का पता लगाने और उसे COM में उजागर करने के लिए समय बिताने की आवश्यकता है।

जब आपको मूल पुस्तकालय को फिर से डिज़ाइन करना होगा तो आपको यह पता लगाना होगा कि, और मुझे लगता है कि यह बहुत अधिक काम होगा।

आपको अपनी कक्षा की गिनती को प्रभावी ढंग से दोगुना या तिगुना करने की आवश्यकता है।

केवल उन वर्गों के लिए जो सार्वजनिक COM इंटरफ़ेस के माध्यम से उजागर होते हैं, जो कि मूल पुस्तकालय के वर्गों का एक छोटा हिस्सा होना चाहिए।

कहा कि, एक अलग स्थिति के लिए, जिसका आपने उल्लेख किया है, जब आप पहले से ही जानते हैं कि आपको शुरुआत से ही एक प्रथम श्रेणी के नागरिक के रूप में COM का समर्थन करना है, तो मुझे लगता है कि आप सही हैं: एक को अलग-अलग एडेप्टर के काम को जोड़ने की परेशानी से बचाना चाहिए और डिजाइन तैयार करना चाहिए COM समर्थन के साथ .NET .NET सीधे।


(+1) हालांकि, "... जो एक छोटी संख्या में होना चाहिए ... मूल पुस्तकालय" केवल कभी-कभी ही सही होता है। "क्लास लाइब्रेरी स्टाइल" में डिज़ाइन किए गए प्रोजेक्ट के बहुत सारे प्रकार हैं, जहां एक वर्ग सार्वजनिक रूप से दिखाई देने वाले उद्देश्य के बराबर है, और यह कि कक्षाएं दिलचस्प कार्यक्षमता को जन्म देती हैं। उस स्थिति में, .NET क्लास काउंट और COM इंटरॉप क्लास काउंट के बीच एक-से-एक मैपिंग हो सकती है।
rwong
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.