EDIT: Saya sudah menulis hasilnya sebagai posting blog .
Compiler C # memperlakukan tipe COM agak ajaib. Misalnya, pernyataan ini terlihat normal ...
Word.Application app = new Word.Application();
... sampai Anda menyadari bahwa itu Application
adalah antarmuka. Memanggil konstruktor pada antarmuka? Yoiks! Ini sebenarnya diterjemahkan ke dalam panggilan ke Type.GetTypeFromCLSID()
dan ke lainnya Activator.CreateInstance
.
Selain itu, dalam C # 4, Anda dapat menggunakan argumen non-ref untuk ref
parameter, dan kompilator hanya menambahkan variabel lokal untuk lulus dengan referensi, membuang hasil:
// FileName parameter is *really* a ref parameter
app.ActiveDocument.SaveAs(FileName: "test.doc");
(Ya, ada banyak argumen yang hilang. Tidakkah parameter opsional bagus? :)
Saya mencoba untuk menyelidiki perilaku kompiler, dan saya gagal memalsukan bagian pertama. Saya dapat melakukan bagian kedua tanpa masalah:
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);
}
}
Saya ingin dapat menulis:
Dummy dummy = new Dummy();
meskipun. Jelas itu akan meledak pada waktu eksekusi, tapi tidak apa-apa. Saya hanya bereksperimen.
Atribut lain yang ditambahkan oleh kompiler untuk COM PIA ( CompilerGenerated
dan TypeIdentifier
) tampaknya tidak melakukan trik ... apa saus ajaibnya?
sumber
dynamic
... kita terlalu terbiasa mengetik statis / kuat untuk melihat mengapa itu penting di luar COM.Jawaban:
Tidak berarti saya ahli dalam hal ini, tetapi saya tersandung baru-baru ini pada apa yang saya pikir Anda inginkan: kelas atribut CoClass .
Lihat jawaban saya untuk pertanyaan serupa tentang Microsoft Speech API , di mana Anda dapat "instantiate" antarmuka
SpVoice
(tapi sungguh, Anda instantiatingSPVoiceClass
).sumber
Antara kamu dan Michael, kamu hampir bisa menyatukan potongan-potongan itu. Saya pikir ini cara kerjanya. (Saya tidak menulis kode, jadi saya mungkin sedikit salah menyebutkannya, tapi saya cukup yakin begini caranya.)
Jika:
kemudian kode tersebut dihasilkan sebagai (IPIAINTERFACE) Activator.CreateInstance (Type.GetTypeFromClsid (GUID OF COCLASSTYPE))
Jika:
maka kode tersebut dibuat seolah-olah Anda akan mengatakan "COCLASSTYPE ()" baru.
Jon, jangan ragu untuk menggangguku atau Sam secara langsung jika Anda memiliki pertanyaan tentang hal ini. FYI, Sam adalah pakar fitur ini.
sumber
Oke, ini hanya untuk memberi sedikit lebih banyak jawaban pada Michael (dia dipersilakan menambahkannya jika dia mau, dalam hal ini saya akan menghapus yang ini).
Melihat PIA asli untuk Word. Aplikasi, ada tiga jenis yang terlibat (mengabaikan acara):
Ada dua antarmuka untuk alasan yang dibicarakan oleh Eric Lippert dalam jawaban lain . Dan di sana, seperti yang Anda katakan, adalah
CoClass
- baik dari segi kelas itu sendiri dan atribut padaApplication
antarmuka.Sekarang jika kita menggunakan tautan PIA dalam C # 4, beberapa di antaranya tertanam dalam biner yang dihasilkan ... tetapi tidak semuanya. Aplikasi yang baru saja membuat instance dari
Application
berakhir dengan jenis ini:Tidak
ApplicationClass
- mungkin karena itu akan dimuat secara dinamis dari tipe COM yang sebenarnya pada waktu eksekusi.Hal lain yang menarik adalah perbedaan dalam kode antara versi tertaut dan versi yang tidak tertaut. Jika Anda mendekompilasi garis
dalam versi referensi itu berakhir sebagai:
sedangkan dalam versi tertaut itu berakhir sebagai
Sehingga terlihat seperti "nyata" PIA membutuhkan
CoClass
atribut, tapi versi terkait tidak karena ada tidak satuCoClass
compiler benar-benar dapat referensi. Itu harus dilakukan secara dinamis.Saya mungkin mencoba memalsukan antarmuka COM menggunakan informasi ini dan melihat apakah saya bisa mendapatkan kompiler untuk menautkannya ...
sumber
Hanya untuk menambahkan sedikit konfirmasi ke jawaban Michael:
Kode ini mengkompilasi dan menjalankan:
Anda membutuhkan keduanya
ComImportAttribute
danGuidAttribute
agar bisa berfungsi.Perhatikan juga informasi ketika Anda mengarahkan mouse ke atas
new IFoo()
: Intellisense menerima informasi dengan benar: Bagus!sumber