Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Saat Anda beroperasi antara COM dan kode terkelola .NET Framework, Anda mungkin mengalami satu atau beberapa masalah umum berikut.
Interop Marshalling
Terkadang, Anda mungkin harus menggunakan jenis data yang bukan bagian dari .NET Framework. Rakitan interop menangani sebagian besar pekerjaan untuk objek COM, tetapi Anda mungkin harus mengontrol jenis data yang digunakan saat objek terkelola terekspos ke COM. Misalnya, struktur dalam pustaka kelas harus menentukan tipe tidak terkelola BStr pada string yang dikirim ke objek COM yang dibuat oleh Visual Basic 6.0 dan versi-versi sebelumnya. Dalam kasus seperti itu, Anda dapat menggunakan atribut MarshalAsAttribute untuk menyebabkan jenis terkelola diekspos sebagai jenis yang tidak dikelola.
Mengekspor string Fixed-Length ke Kode Tidak Terkelola
Di Visual Basic 6.0 dan versi yang lebih lama, string diekspor ke objek COM sebagai urutan byte tanpa karakter penghentian null. Untuk kompatibilitas dengan bahasa lain, Visual Basic .NET menyertakan karakter penghentian saat mengekspor string. Cara terbaik untuk mengatasi ketidaksesuaian ini adalah dengan mengekspor string yang tidak memiliki karakter penghentian sebagai array Byte atau Char.
Mengekspor Hierarki Pewarisan
Hierarki kelas terkelola merata saat diekspos sebagai objek COM. Misalnya, jika Anda menentukan kelas dasar dengan anggota, lalu mewarisi kelas dasar di kelas turunan yang diekspos sebagai objek COM, klien yang menggunakan kelas turunan dalam objek COM tidak akan dapat menggunakan anggota yang diwariskan. Anggota kelas dasar hanya dapat diakses dari objek COM sebagai instans kelas dasar, dan kemudian hanya jika kelas dasar juga dibuat sebagai objek COM.
Metode Kelebihan Beban
Meskipun Anda dapat membuat metode kelebihan beban dengan Visual Basic, metode tersebut tidak didukung oleh COM. Ketika kelas yang berisi metode kelebihan beban diekspos sebagai objek COM, nama metode baru dihasilkan untuk metode yang kelebihan beban.
Misalnya, pertimbangkan kelas yang memiliki dua kelebihan beban metode Synch. Ketika kelas diekspos sebagai objek COM, nama metode baru yang dihasilkan dapat Synch dan Synch_2.
Penggantian nama dapat menyebabkan dua masalah bagi konsumen objek COM.
Klien mungkin tidak mengharapkan nama metode yang dihasilkan.
Nama metode yang dihasilkan di kelas yang diekspos sebagai objek COM dapat berubah ketika kelebihan beban baru ditambahkan ke kelas atau kelas dasarnya. Ini dapat menyebabkan masalah penerapan versi.
Untuk menyelesaikan kedua masalah, beri setiap metode nama yang unik, alih-alih menggunakan kelebihan beban, ketika Anda mengembangkan objek yang akan diekspos sebagai objek COM.
Penggunaan Objek COM Melalui Rakitan Interop
Anda menggunakan rakitan interop hampir seolah-olah mereka adalah pengganti kode terkelola untuk objek COM yang diwakilinya. Namun, karena mereka adalah pembungkus dan bukan objek COM yang sebenarnya, ada beberapa perbedaan antara menggunakan rakitan interop dan rakitan standar. Area perbedaan ini termasuk paparan kelas, dan jenis data untuk parameter dan nilai pengembalian.
Kelas yang Diekspos sebagai Antarmuka dan Kelas
Tidak seperti kelas dalam rakitan standar, kelas COM diekspos dalam rakitan interop sebagai antarmuka dan kelas yang mewakili kelas COM. Nama antarmuka identik dengan kelas COM. Nama kelas interop sama dengan kelas COM asli, tetapi dengan kata "Kelas" ditambahkan. Misalnya, Anda memiliki proyek dengan referensi ke perakitan interop untuk objek COM. Jika kelas COM diberi nama MyComClass, IntelliSense dan Browser Objek menampilkan antarmuka bernama MyComClass dan kelas bernama MyComClassClass.
Membuat Instans Kelas .NET Framework
Umumnya, Anda membuat instans kelas .NET Framework menggunakan pernyataan New dengan nama kelas. Memiliki kelas COM yang diwakili oleh rakitan interop adalah satu kasus di mana Anda dapat menggunakan pernyataan New dengan antarmuka. Kecuali Anda menggunakan kelas COM dengan pernyataan Inherits, Anda dapat menggunakan antarmuka seperti yang Anda lakukan di kelas. Kode berikut menunjukkan cara membuat objek Command dalam proyek yang memiliki referensi ke objek COM Pustaka Microsoft ActiveX Data Objects 2.8:
Dim cmd As New ADODB.Command
Namun, jika Anda menggunakan kelas COM sebagai dasar untuk kelas turunan, Anda harus menggunakan kelas interop yang mewakili kelas COM, seperti dalam kode berikut:
Class DerivedCommand
Inherits ADODB.CommandClass
End Class
Nota
Rakitan interop secara implisit mengimplementasikan antarmuka yang mewakili kelas COM. Anda tidak boleh mencoba menggunakan pernyataan Implements untuk mengimplementasikan antarmuka ini atau kesalahan akan dihasilkan.
Jenis Data untuk Parameter dan Nilai Yang Dikembalikan
Tidak seperti anggota rakitan standar, anggota rakitan interop mungkin memiliki jenis data yang berbeda dari yang digunakan dalam deklarasi objek asli. Meskipun rakitan interop secara implisit mengonversi jenis COM ke jenis runtime bahasa umum yang kompatibel, Anda harus memperhatikan jenis data yang digunakan oleh kedua sisi untuk mencegah kesalahan runtime. Misalnya, dalam objek COM yang dibuat di Visual Basic 6.0 dan versi yang lebih lama, nilai jenis Integer mengasumsikan jenis setara .NET Framework, Short. Disarankan agar Anda menggunakan Browser Objek untuk memeriksa karakteristik anggota yang diimpor sebelum Anda menggunakannya.
Metode COM tingkat modul
Sebagian besar objek COM digunakan dengan membuat instans kelas COM menggunakan kata kunci New lalu memanggil metode objek. Satu pengecualian untuk aturan ini melibatkan objek COM yang berisi kelas COM AppObj atau GlobalMultiUse. Kelas seperti itu menyerupai metode tingkat modul di kelas Visual Basic .NET. Visual Basic 6.0 dan versi yang lebih lama secara implisit membuat instans objek tersebut untuk Anda pertama kalinya Anda memanggil salah satu metodenya. Misalnya, di Visual Basic 6.0 Anda dapat menambahkan referensi ke Microsoft DAO 3.6 Object Library dan memanggil metode DBEngine tanpa terlebih dahulu membuat instans:
Dim db As DAO.Database
' Open the database.
Set db = DBEngine.OpenDatabase("C:\nwind.mdb")
' Use the database object.
Visual Basic .NET mengharuskan Anda selalu membuat instans objek COM sebelum Anda dapat menggunakan metodenya. Untuk menggunakan metode ini di Visual Basic, deklarasikan variabel kelas yang diinginkan dan gunakan kata kunci baru untuk menetapkan objek ke variabel objek. Kata kunci Shared dapat digunakan saat Anda ingin memastikan bahwa hanya satu instans kelas yang dibuat.
' Class level variable.
Shared DBEngine As New DAO.DBEngine
Sub DAOOpenRecordset()
Dim db As DAO.Database
Dim rst As DAO.Recordset
Dim fld As DAO.Field
' Open the database.
db = DBEngine.OpenDatabase("C:\nwind.mdb")
' Open the Recordset.
rst = db.OpenRecordset(
"SELECT * FROM Customers WHERE Region = 'WA'",
DAO.RecordsetTypeEnum.dbOpenForwardOnly,
DAO.RecordsetOptionEnum.dbReadOnly)
' Print the values for the fields in the debug window.
For Each fld In rst.Fields
Debug.WriteLine(fld.Value.ToString & ";")
Next
Debug.WriteLine("")
' Close the Recordset.
rst.Close()
End Sub
Kesalahan yang Tidak Tertangani dalam Penanganan Peristiwa
Satu masalah interop umum melibatkan kesalahan dalam penanganan aktivitas yang menangani peristiwa yang dimunculkan oleh objek COM. Kesalahan tersebut diabaikan kecuali Anda secara khusus memeriksa kesalahan menggunakan pernyataan On Error atau Try...Catch...Finally. Misalnya, contoh berikut berasal dari proyek Visual Basic .NET yang memiliki referensi ke objek COM Pustaka Microsoft ActiveX Data Objects 2.8.
' To use this example, add a reference to the
' Microsoft ActiveX Data Objects 2.8 Library
' from the COM tab of the project references page.
Dim WithEvents cn As New ADODB.Connection
Sub ADODBConnect()
cn.ConnectionString = "..."
cn.Open()
MsgBox(cn.ConnectionString)
End Sub
Private Sub Form1_Load(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles MyBase.Load
ADODBConnect()
End Sub
Private Sub cn_ConnectComplete(
ByVal pError As ADODB.Error,
ByRef adStatus As ADODB.EventStatusEnum,
ByVal pConnection As ADODB.Connection) Handles cn.ConnectComplete
' This is the event handler for the cn_ConnectComplete event raised
' by the ADODB.Connection object when a database is opened.
Dim x As Integer = 6
Dim y As Integer = 0
Try
x = CInt(x / y) ' Attempt to divide by zero.
' This procedure would fail silently without exception handling.
Catch ex As Exception
MsgBox("There was an error: " & ex.Message)
End Try
End Sub
Contoh ini menimbulkan kesalahan seperti yang diharapkan. Namun, jika Anda mencoba contoh yang sama tanpa blok Try...Catch...Finally, kesalahan diabaikan seolah-olah Anda menggunakan pernyataan OnError Resume Next. Tanpa penanganan kesalahan, pembagian dengan nol secara diam-diam gagal. Karena kesalahan tersebut tidak pernah menimbulkan kesalahan pengecualian yang tidak tertangani, penting bahwa Anda menggunakan beberapa bentuk penanganan pengecualian di penanganan aktivitas yang menangani peristiwa dari objek COM.
Memahami kesalahan interop COM
Tanpa penanganan kesalahan, panggilan interop sering menghasilkan kesalahan yang memberikan sedikit informasi. Jika memungkinkan, gunakan penanganan kesalahan terstruktur untuk memberikan informasi lebih lanjut tentang masalah ketika terjadi. Ini bisa sangat membantu ketika Anda men-debug aplikasi. Misalnya:
Try
' Place call to COM object here.
Catch ex As Exception
' Display information about the failed call.
End Try
Anda dapat menemukan informasi seperti deskripsi kesalahan, HRESULT, dan sumber kesalahan COM dengan memeriksa konten objek pengecualian.
Masalah Kontrol ActiveX
Sebagian besar kontrol ActiveX yang berfungsi dengan Visual Basic 6.0 berfungsi dengan Visual Basic .NET tanpa masalah. Pengecualian utama adalah kontrol kontainer, atau kontrol yang secara visual berisi kontrol lain. Beberapa contoh kontrol lama yang tidak berfungsi dengan benar dengan Visual Studio adalah sebagai berikut:
Kontrol Frame Microsoft Forms 2.0
Up-Down kontrol, juga dikenal sebagai kontrol putar
Kontrol Tab Sheridan
Hanya ada beberapa solusi untuk masalah kontrol ActiveX yang tidak didukung. Anda dapat memigrasikan kontrol yang ada ke Visual Studio jika Anda memiliki kode sumber asli. Jika tidak, Anda dapat memeriksa dengan vendor perangkat lunak untuk versi kontrol yang diperbarui dan kompatibel dengan .NET untuk menggantikan kontrol ActiveX yang tidak didukung.
Meneruskan Properti ReadOnly dari Controls ByRef
Visual Basic terkadang menimbulkan kesalahan COM, seperti "Kesalahan 0x800A017F CTL_E_SETNOTSUPPORTED", saat Anda meneruskan properti ReadOnly dari beberapa kontrol ActiveX yang lebih lama sebagai parameter ByRef ke prosedur lain. Panggilan prosedur serupa dari Visual Basic 6.0 tidak menimbulkan kesalahan, dan parameter diperlakukan seolah-olah Anda meneruskannya berdasarkan nilai. Pesan kesalahan Visual Basic .NET menunjukkan bahwa Anda mencoba mengubah properti yang tidak memiliki prosedur properti Set.
Jika Anda memiliki akses ke prosedur yang dipanggil, Anda dapat mencegah kesalahan ini dengan menggunakan kata kunci ByVal untuk mendeklarasikan parameter yang menerima properti ReadOnly. Misalnya:
Sub ProcessParams(ByVal c As Object)
'Use the arguments here.
End Sub
Jika Anda tidak memiliki akses ke kode sumber untuk prosedur yang dipanggil, Anda dapat memaksa properti untuk dilewatkan sebagai nilai dengan menambahkan sepasang tanda kurung tambahan di sekitar prosedur panggilan. Misalnya, dalam proyek yang memiliki referensi ke objek COM Pustaka Microsoft ActiveX Data Objects 2.8, Anda dapat menggunakan:
Sub PassByVal(ByVal pError As ADODB.Error)
' The extra set of parentheses around the arguments
' forces them to be passed by value.
ProcessParams((pError.Description))
End Sub
Penyebaran Rakitan yang Mengungkap Interop
Menyebarkan rakitan yang mengekspos antarmuka COM menghadirkan beberapa tantangan unik. Misalnya, potensi masalah terjadi ketika aplikasi terpisah mereferensikan rakitan COM yang sama. Situasi ini umum terjadi ketika versi baru rakitan diinstal dan aplikasi lain masih menggunakan versi lama rakitan. Jika Anda menghapus instalan rakitan yang berbagi DLL, Anda dapat secara tidak sengaja membuatnya tidak tersedia untuk rakitan lain.
Untuk menghindari masalah ini, Anda harus menginstal rakitan bersama ke Global Assembly Cache (GAC) dan menggunakan MergeModule untuk komponen. Jika Anda tidak dapat menginstal aplikasi di GAC, aplikasi harus diinstal ke CommonFilesFolder dalam subdirektori khusus versi.
Rakitan yang tidak dibagikan harus terletak berdampingan di direktori dengan aplikasi panggilan.