C # कंपाइलर COM प्रकारों का पता कैसे लगाता है?


168

संपादित करें: मैंने परिणामों को एक ब्लॉग पोस्ट के रूप में लिखा है ।


C # कंपाइलर COM प्रकार को कुछ जादुई तरीके से व्यवहार करता है। उदाहरण के लिए, यह कथन सामान्य लग रहा है ...

Word.Application app = new Word.Application();

... जब तक आप महसूस करते हैं कि Applicationयह एक इंटरफ़ेस है। एक इंटरफ़ेस पर एक निर्माता को बुला रहा है? Yoiks! यह वास्तव में एक कॉल में Type.GetTypeFromCLSID()और दूसरे में अनुवाद हो जाता है Activator.CreateInstance

इसके अतिरिक्त, C # 4 में, आप refमापदंडों के लिए गैर-रेफरी तर्क का उपयोग कर सकते हैं , और संकलक सिर्फ संदर्भ द्वारा पारित करने के लिए एक स्थानीय चर जोड़ता है, परिणाम को छोड़ते हुए:

// FileName parameter is *really* a ref parameter
app.ActiveDocument.SaveAs(FileName: "test.doc");

(हाँ, दलीलों का एक समूह गायब है। वैकल्पिक पैरामीटर अच्छे नहीं हैं? :)

मैं संकलक व्यवहार की जांच करने की कोशिश कर रहा हूं, और मैं पहले भाग को नकली करने में विफल रहा हूं। मैं बिना किसी समस्या के दूसरा भाग कर सकता हूं:

using System;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;

[ComImport, GuidAttribute("00012345-0000-0000-0000-000000000011")]
public interface Dummy
{
    void Foo(ref int x);
}

class Test
{
    static void Main()
    {
        Dummy dummy = null;
        dummy.Foo(10);
    }
}

मैं लिखना चाहूंगा:

Dummy dummy = new Dummy();

हालांकि। जाहिर है यह निष्पादन के समय धमाकेदार होगा, लेकिन यह ठीक है। मैं सिर्फ प्रयोग कर रहा हूं।

लिंक किए गए COM PIA ( CompilerGeneratedऔर TypeIdentifier) के लिए संकलक द्वारा जोड़े गए अन्य गुण चाल नहीं लगते ... जादू की चटनी क्या है?


11
वैकल्पिक पैरामीटर अच्छे नहीं हैं? IMO, नहीं वे अच्छे नहीं हैं। Microsoft Office COM इंटरफेस में दोष को C # में ब्लोट जोड़कर ठीक करने का प्रयास कर रहा है।
मेहरदाद अफश्री

18
@ मेहरदाद: वैकल्पिक पैरामीटर COM से परे उपयोगी हैं, बिल्कुल। आपको डिफ़ॉल्ट मानों से सावधान रहने की आवश्यकता है, लेकिन उनके और नामित तर्कों के बीच, उपयोग करने योग्य अपरिवर्तनीय प्रकार का निर्माण करना बहुत आसान है।
जॉन स्कीट

1
सच। विशेष रूप से, नामित मापदंडों को कुछ गतिशील वातावरण के साथ इंटरोप के लिए व्यावहारिक रूप से आवश्यक हो सकता है। यकीन है, एक शक के बिना, यह एक उपयोगी विशेषता है लेकिन इसका मतलब यह नहीं है कि यह मुफ्त में आता है। इसकी सादगी (स्पष्ट रूप से स्पष्ट डिजाइन लक्ष्य) की लागत है। व्यक्तिगत रूप से, मुझे लगता है कि सी # उन सुविधाओं के लिए अद्भुत है, जिन्हें टीम ने छोड़ दिया (अन्यथा, यह सी ++ क्लोन हो सकता था)। C # टीम महान है लेकिन एक कॉर्पोरेट माहौल शायद ही राजनीति मुक्त हो सकता है। मुझे लगता है कि एंडर्स खुद इस बारे में बहुत खुश नहीं थे क्योंकि उन्होंने अपनी पीडीसी'08 वार्ता में कहा था: "हमें जहां हम थे वहां वापस आने में दस साल लग गए।"
मेहरदाद अफश्री

7
मैं मानता हूं कि टीम को जटिलता पर कड़ी नजर रखने की जरूरत होगी। डायनेमिक सामान अधिकांश डेवलपर्स के लिए थोड़े मूल्य के लिए बहुत अधिक जटिलता जोड़ता है , लेकिन कुछ डेवलपर्स के लिए उच्च मूल्य ।
जॉन स्कीट

1
मैंने कई स्थानों पर इसके उपयोग पर चर्चा करने के लिए फ्रेमवर्क डेवलपर्स को देखा है। IMO अभी समय है जब तक हम इसके लिए एक अच्छा उपयोग नहीं पाते हैं dynamic... हम अभी भी स्थिर / मजबूत टाइपिंग के लिए उपयोग कर रहे हैं यह देखने के लिए कि यह COM के बाहर क्यों बात करेगा।
5

जवाबों:


145

किसी भी तरह से मैं इसमें विशेषज्ञ नहीं हूं, लेकिन मैं हाल ही में इस बात पर अड़ गया हूं कि मुझे लगता है कि आप चाहते हैं: CoClass विशेषता वर्ग।

[System.Runtime.InteropServices.CoClass(typeof(Test))]
public interface Dummy { }

एक coclass एक या अधिक इंटरफेस के ठोस कार्यान्वयन की आपूर्ति करता है। COM में, इस तरह के ठोस कार्यान्वयन किसी भी प्रोग्रामिंग भाषा में लिखे जा सकते हैं जो COM घटक विकास, जैसे डेल्फी, सी ++, विज़ुअल बेसिक, आदि का समर्थन करते हैं।

Microsoft भाषण एपीआई के बारे में एक समान प्रश्न के लिए मेरा जवाब देखें , जहां आप इंटरफ़ेस को "तुरंत" करने में सक्षम हैं SpVoice(लेकिन वास्तव में, आप तत्काल हैं SPVoiceClass)।

[CoClass(typeof(SpVoiceClass))]
public interface SpVoice : ISpeechVoice, _ISpeechVoiceEvents_Event { }

2
बहुत दिलचस्प - बाद में इसे आजमाएंगे। लिंक किए गए PIA प्रकारों में हालांकि CoClass नहीं है। शायद यह जोड़ने की प्रक्रिया के साथ कुछ करना है - मैं मूल PIA में एक नज़र हूँ ...
जॉन स्कीट

64
एरिक लिपर्ट और जॉन स्कीट ने भी जब स्वीकार किए गए उत्तर को लिखकर भयानक होने के लिए +1 किया;) कोक्लास का उल्लेख करने के लिए वास्तव में, +1 नहीं।
ओरेगनगॉस्ट

61

तुम्हारे और माइकल के बीच तुम लगभग टुकड़े एक साथ डाल दिया है। मुझे लगता है कि यह कैसे काम करता है। (मैंने कोड नहीं लिखा था, इसलिए मैं इसे थोड़ा गलत बता सकता हूं, लेकिन मुझे पूरा यकीन है कि यह इसी तरह से चलता है।)

अगर:

  • आप एक इंटरफ़ेस प्रकार के "नए" हैं, और
  • इंटरफ़ेस प्रकार में एक ज्ञात कोकलैस है, और
  • आप इस इंटरफ़ेस के लिए "नो पिया" सुविधा का उपयोग कर रहे हैं

तब कोड (IPIAINTERFACE) उत्प्रेरक के रूप में उत्पन्न होता है। क्रिएशनइन्स्टेंस (Type.GetTypeFromClsid (COCLASSTYPE का गाइड))

अगर:

  • आप एक इंटरफ़ेस प्रकार के "नए" हैं, और
  • इंटरफ़ेस प्रकार में एक ज्ञात कोकलैस है, और
  • आप इस इंटरफ़ेस के लिए "नो पिया" सुविधा का उपयोग नहीं कर रहे हैं

तब कोड उत्पन्न होता है जैसे कि आपने "नया COCLASSTYPE ()" कहा था।

जॉन, इस सामान के बारे में प्रश्न होने पर सीधे मुझे या सैम को बग मुक्त करने के लिए स्वतंत्र महसूस करें। FYI करें, सैम इस सुविधा का विशेषज्ञ है।


36

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

Word.Application के लिए मूल PIA को देखते हुए, इसमें तीन प्रकार शामिल होते हैं (घटनाओं की अनदेखी):

[ComImport, TypeLibType(...), Guid("..."), DefaultMember("Name")]
public interface _Application
{
     ...
}

[ComImport, Guid("..."), CoClass(typeof(ApplicationClass))]
public interface Application : _Application
{
}

[ComImport, ClassInterface(...), ComSourceInterfaces("..."), Guid("..."), 
 TypeLibType((short) 2), DefaultMember("Name")]
public class ApplicationClass : _Application, Application
{
}

कारणों के लिए दो इंटरफेस हैं जो एरिक लिपर्ट एक और जवाब में बात करते हैं । और वहाँ, जैसा कि आपने कहा, CoClass- दोनों ही वर्ग के संदर्भ में और Applicationइंटरफ़ेस पर विशेषता है।

अब अगर हम C # 4 में PIA लिंकिंग का उपयोग करते हैं, तो इसका कुछ परिणामी बाइनरी में एम्बेडेड है ... लेकिन यह सब नहीं। एक आवेदन जो सिर्फApplication इन प्रकारों के साथ समाप्त होने का एक उदाहरण बनाता है :

[ComImport, TypeIdentifier, Guid("..."), CompilerGenerated]
public interface _Application

[ComImport, Guid("..."), CompilerGenerated, TypeIdentifier]
public interface Application : _Application

नहीं ApplicationClass- संभवतः क्योंकि निष्पादन समय पर वास्तविक COM प्रकार से गतिशील रूप से लोड किया जाएगा ।

एक और दिलचस्प बात यह है कि लिंक किए गए संस्करण और गैर-लिंक किए गए संस्करण के बीच कोड में अंतर है। यदि आप लाइन अपघटित करते हैं

Word.Application application = new Word.Application();

में संदर्भित संस्करण के रूप में समाप्त होता है:

Application application = new ApplicationClass();

जबकि लिंक किए गए संस्करण में यह समाप्त होता है

Application application = (Application) 
    Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("...")));

तो ऐसा लगता है कि "वास्तविक" पीआईए को CoClassविशेषता की आवश्यकता है , लेकिन लिंक किए गए संस्करण में ऐसा नहीं है क्योंकि संकलक नहीं है CoClassवास्तव में संदर्भ हो सकता है। इसे गतिशील रूप से करना होगा।

मैं इस जानकारी का उपयोग करके एक COM इंटरफ़ेस को नकली करने की कोशिश कर सकता हूं और देख सकता हूं कि क्या मुझे इसे लिंक करने के लिए कंपाइलर मिल सकता है ...


27

बस माइकल के जवाब की पुष्टि करने के लिए थोड़ा जोड़ना:

निम्नलिखित कोड संकलित करता है और चलाता है:

public class Program
{
    public class Foo : IFoo
    {
    }

    [Guid("00000000-0000-0000-0000-000000000000")]
    [CoClass(typeof(Foo))]
    [ComImport]
    public interface IFoo
    {
    }

    static void Main(string[] args)
    {
        IFoo foo = new IFoo();
    }
}

आपको काम करने ComImportAttributeके GuidAttributeलिए और इसके लिए दोनों की जरूरत है ।

जब आप माउस को हॉवर करते हैं, तो भी इस पर ध्यान दें new IFoo(): इन्टेलिसेन्स सूचना को ठीक से उठाता है: अच्छा!


धन्यवाद, मैं कोशिश कर रहा था, लेकिन मैं याद आ रही थी ComImport विशेषता है, लेकिन मैं जब मैं मैं स्रोत कोड के लिए जाना F12 का उपयोग कर केवल पता चलता है काम कर रहा था CoClass और Guid , क्यों है?
एहसान सज्जाद
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.