Birlikte Çalışabilirlik İle İlgili Sorun Giderme (Visual Basic)

COM ile .NET Framework yönetilen kodu arasında birlikte çalışırken, aşağıdaki yaygın sorunlardan biriyle veya daha fazlayla karşılaşabilirsiniz.

Birlikte Çalışma Marshalllama

Bazen, .NET Framework parçası olmayan veri türlerini kullanmanız gerekebilir. Birlikte çalışma derlemeleri COM nesneleri için işin çoğunu işler, ancak yönetilen nesneler COM'a sunulduğunda kullanılan veri türlerini denetlemeniz gerekebilir. Örneğin, sınıf kitaplıklarındaki yapılar, Visual Basic 6.0 ve önceki sürümler tarafından oluşturulan COM nesnelerine gönderilen dizelerde yönetilmeyen türü belirtmelidir BStr . Böyle durumlarda, yönetilen türlerin MarshalAsAttribute yönetilmeyen türler olarak kullanıma sunulmalarına neden olmak için özniteliğini kullanabilirsiniz.

Fixed-Length Dizelerini Yönetilmeyen Koda Aktarma

Visual Basic 6.0 ve önceki sürümlerde dizeler, null sonlandırma karakteri olmadan bayt dizisi olarak COM nesnelerine dışarı aktarılır. Diğer dillerle uyumluluk için, Visual Basic .NET dizeleri dışarı aktarırken bir sonlandırma karakteri içerir. Bu uyumsuzluğu gidermenin en iyi yolu, sonlandırma karakteri olmayan dizeleri veya Chardizileri Byte olarak dışarı aktarmaktır.

Devralma Hiyerarşilerini Dışarı Aktarma

Yönetilen sınıf hiyerarşileri, COM nesneleri olarak kullanıma sunulduğunda düzleştirilmiştir. Örneğin, bir üyeyle bir temel sınıf tanımlarsanız ve ardından COM nesnesi olarak kullanıma sunulan türetilmiş bir sınıfta temel sınıfı devralırsanız, COM nesnesinde türetilmiş sınıfı kullanan istemciler devralınan üyeleri kullanamaz. Temel sınıf üyelerine COM nesnelerinden yalnızca bir temel sınıfın örnekleri olarak ve yalnızca temel sınıf com nesnesi olarak oluşturulduysa erişilebilir.

Aşırı Yüklenmiş Yöntemler

Visual Basic ile aşırı yüklenmiş yöntemler oluşturabilmenize rağmen, bunlar COM tarafından desteklenmez. Aşırı yüklenmiş yöntemler içeren bir sınıf COM nesnesi olarak kullanıma sunulduğunda, aşırı yüklenmiş yöntemler için yeni yöntem adları oluşturulur.

Örneğin, yönteminin iki aşırı yüklemesine Synch sahip bir sınıf düşünün. Sınıf bir COM nesnesi olarak kullanıma sunulduğunda, yeni oluşturulan yöntem adları ve Synch_2olabilirSynch.

Yeniden adlandırma, COM nesnesinin tüketicileri için iki soruna neden olabilir.

  1. İstemciler oluşturulan yöntem adlarını beklemeyebilir.

  2. COM nesnesi olarak kullanıma sunulan sınıfta oluşturulan yöntem adları, sınıfa veya temel sınıfına yeni aşırı yüklemeler eklendiğinde değişebilir. Bu, sürüm oluşturma sorunlarına neden olabilir.

Her iki sorunu da çözmek için, COM nesneleri olarak kullanıma sunulacak nesneler geliştirirken aşırı yükleme kullanmak yerine her yönteme benzersiz bir ad verin.

Birlikte Çalışma Derlemeleri Aracılığıyla COM Nesnelerinin Kullanımı

Birlikte çalışma derlemelerini neredeyse temsil ettikleri COM nesneleri için yönetilen kod değişimi gibi kullanırsınız. Ancak bunlar gerçek COM nesneleri değil sarmalayıcılar olduğundan, birlikte çalışma derlemelerini ve standart derlemeleri kullanma arasında bazı farklar vardır. Bu fark alanları sınıfların açığa çıkarmasını ve parametreler ve dönüş değerleri için veri türlerini içerir.

Hem Arabirimler hem de Sınıflar Olarak Kullanıma Sunulan Sınıflar

Standart derlemelerdeki sınıfların aksine, COM sınıfları birlikte çalışma derlemelerinde hem arabirim hem de COM sınıfını temsil eden bir sınıf olarak kullanıma sunulur. Arabirimin adı COM sınıfının adıyla aynıdır. Birlikte çalışma sınıfının adı özgün COM sınıfının adıyla aynıdır, ancak "Sınıf" sözcüğü eklenir. Örneğin, COM nesnesi için birlikte çalışma derlemesine başvuru içeren bir projeniz olduğunu varsayalım. COM sınıfı adlıysa MyComClass, IntelliSense ve Object Browser adlı bir arabirim ve adlı MyComClassMyComClassClassbir sınıf gösterir.

.NET Framework Sınıfının Örneklerini Oluşturma

Genellikle, sınıf adıyla deyimini kullanarak bir .NET Framework sınıfının örneğini New oluşturursunuz. Birlikte çalışma derlemesi tarafından temsil edilen bir COM sınıfına sahip olmak, deyimini bir arabirimle kullanabileceğiniz New tek durumdur. COM sınıfını bir Inherits deyimiyle kullanmıyorsanız, arabirimini bir sınıf gibi kullanabilirsiniz. Aşağıdaki kod, Microsoft ActiveX Veri Nesneleri 2.8 Kitaplığı COM nesnesine başvurusu olan bir projede nasıl nesne oluşturulacağını Command gösterir:

Dim cmd As New ADODB.Command

Ancak, türetilmiş bir sınıfın temeli olarak COM sınıfını kullanıyorsanız, aşağıdaki kodda olduğu gibi COM sınıfını temsil eden birlikte çalışma sınıfını kullanmanız gerekir:

Class DerivedCommand
    Inherits ADODB.CommandClass
End Class

Not

Birlikte çalışma derlemeleri COM sınıflarını temsil eden arabirimleri örtük olarak uygular. Bu arabirimleri uygulamak için deyimini Implements kullanmayı denememelisiniz, aksi takdirde bir hata oluşur.

Parametreler ve Dönüş Değerleri için Veri Türleri

Standart derlemelerin üyelerinden farklı olarak, birlikte çalışma derleme üyeleri özgün nesne bildiriminde kullanılanlardan farklı veri türlerine sahip olabilir. Birlikte çalışma derlemeleri COM türlerini örtük olarak uyumlu ortak dil çalışma zamanı türlerine dönüştürse de, çalışma zamanı hatalarını önlemek için her iki taraf tarafından kullanılan veri türlerine dikkat etmelisiniz. Örneğin, Visual Basic 6.0 ve önceki sürümlerde oluşturulan COM nesnelerinde, türündeki Integer değerler eşdeğer .NET Framework tür Shortolduğunu varsayar. İçeri aktarılan üyeleri kullanmadan önce özelliklerini incelemek için Object Browser'ı kullanmanız önerilir.

Modül düzeyi COM yöntemleri

COM nesnelerinin çoğu, anahtar sözcüğünü kullanarak com sınıfının bir örneğini New oluşturup nesnenin yöntemlerini çağırarak kullanılır. Bu kuralın bir özel durumu, veya GlobalMultiUse COM sınıfları içeren COM nesnelerini içerirAppObj. Bu tür sınıflar Visual Basic .NET sınıflarındaki modül düzeyi yöntemlerine benzer. Visual Basic 6.0 ve önceki sürümler, yöntemlerinden birini ilk kez çağırdığınızda bu tür nesnelerin örneklerini örtük olarak oluşturur. Örneğin, Visual Basic 6.0'da Microsoft DAO 3.6 Nesne Kitaplığı'na bir başvuru ekleyebilir ve önce bir örnek oluşturmadan yöntemini çağırabilirsiniz DBEngine :

Dim db As DAO.Database  
' Open the database.  
Set db = DBEngine.OpenDatabase("C:\nwind.mdb")  
' Use the database object.  

Visual Basic .NET, yöntemlerini kullanabilmeniz için her zaman COM nesnelerinin örneklerini oluşturmanızı gerektirir. Visual Basic'te bu yöntemleri kullanmak için istenen sınıfın değişkenini bildirin ve nesnesini nesne değişkenine atamak için yeni anahtar sözcüğünü kullanın. sınıfının Shared yalnızca bir örneğinin oluşturulduğundan emin olmak istediğinizde anahtar sözcüğü kullanılabilir.

' 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

Olay İşleyicilerinde İşlenmeyen Hatalar

Yaygın bir birlikte çalışma sorunu, COM nesneleri tarafından tetiklenen olayları işleyen olay işleyicilerindeki hataları içerir. Veya Try...Catch...Finally deyimlerini kullanarak On Error hataları özellikle denetlemediğiniz sürece bu tür hatalar yoksayılır. Örneğin, aşağıdaki örnek, Microsoft ActiveX Veri Nesneleri 2.8 Kitaplığı COM nesnesine başvuru içeren bir Visual Basic .NET projesinden alınmıştır.

' 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 =
    "Provider=Microsoft.Jet.OLEDB.4.0;" &
    "Data Source=C:\NWIND.MDB"
    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

Bu örnek beklendiği gibi bir hata oluşturur. Ancak, aynı örneği blok olmadan Try...Catch...Finally denerseniz, deyimini kullanmışsınız OnError Resume Next gibi hata yoksayılır. Hata işleme olmadan sıfıra bölme işlemi sessizce başarısız olur. Bu tür hatalar hiçbir zaman işlenmeyen özel durum hataları oluşturmadığından, COM nesnelerinden olayları işleyen olay işleyicilerinde bir tür özel durum işleme kullanmanız önemlidir.

COM birlikte çalışma hatalarını anlama

Hata işleme olmadan birlikte çalışma çağrıları genellikle çok az bilgi sağlayan hatalar oluşturur. Mümkün olduğunda, ortaya çıkan sorunlar hakkında daha fazla bilgi sağlamak için yapılandırılmış hata işlemeyi kullanın. Bu, özellikle uygulamalarda hata ayıklarken yararlı olabilir. Örnek:

Try
    ' Place call to COM object here.
Catch ex As Exception
    ' Display information about the failed call.
End Try

Özel durum nesnesinin içeriğini inceleyerek hata açıklaması, HRESULT ve COM hatalarının kaynağı gibi bilgileri bulabilirsiniz.

ActiveX Denetimi Sorunları

Visual Basic 6.0 ile çalışan ActiveX denetimlerinin çoğu Visual Basic .NET ile sorunsuz çalışır. Ana özel durumlar kapsayıcı denetimleri veya görsel olarak diğer denetimleri içeren denetimlerdir. Visual Studio ile düzgün çalışmayan bazı eski denetim örnekleri şunlardır:

  • Microsoft Forms 2.0 Çerçeve denetimi

  • döndürme denetimi olarak da bilinen Up-Down denetimi

  • Sheridan Sekme Denetimi

Desteklenmeyen ActiveX denetimi sorunları için yalnızca birkaç geçici çözüm vardır. Özgün kaynak koduna sahipseniz mevcut denetimleri Visual Studio'ya geçirebilirsiniz. Aksi takdirde, yazılım satıcılarına güncelleştirilmiş olup olmadığını kontrol edebilirsiniz. Desteklenmeyen ActiveX denetimlerini değiştirmek için denetimlerin NET uyumlu sürümleri.

ByRef Denetimlerinin ReadOnly Özelliklerini Geçirme

Bazı eski ActiveX denetimlerinin özelliklerini diğer yordamlara parametre olarak ByRef geçirdiğinizde ReadOnly Visual Basic .NET bazen "Hata 0x800A017F CTL_E_SETNOTSUPPORTED" gibi COM hataları oluşturur. Visual Basic 6.0'dan gelen benzer yordam çağrıları bir hata oluşturmaz ve parametreler değere göre geçirmişsiniz gibi kabul edilir. Visual Basic .NET hata iletisi, özellik Set yordamı olmayan bir özelliği değiştirmeye çalıştığınızı gösterir.

Çağrılan yordama erişiminiz varsa, özellikleri kabul ReadOnly eden parametreleri bildirmek için anahtar sözcüğünü ByVal kullanarak bu hatayı önleyebilirsiniz. Örnek:

Sub ProcessParams(ByVal c As Object)
    'Use the arguments here.
End Sub

Çağrılan yordamın kaynak koduna erişiminiz yoksa, çağırma yordamının çevresine fazladan bir köşeli ayraç kümesi ekleyerek özelliğin değere göre geçirilmesini zorlayabilirsiniz. Örneğin, Microsoft ActiveX Veri Nesneleri 2.8 Kitaplığı COM nesnesine başvuru içeren bir projede şunları kullanabilirsiniz:

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

Birlikte Çalışma Kullanıma Sunan Derlemeleri Dağıtma

COM arabirimlerini kullanıma sunan derlemelerin dağıtılması bazı benzersiz zorluklara neden olur. Örneğin, ayrı uygulamalar aynı COM derlemesine başvurduğunda olası bir sorun oluşur. Bu durum, derlemenin yeni bir sürümü yüklendiğinde ve başka bir uygulama derlemenin eski sürümünü kullanmaya devam ettiğinde yaygındır. DLL'yi paylaşan bir derlemeyi kaldırırsanız, istemeden diğer derlemeler için kullanılamaz duruma getirebilirsiniz.

Bu sorunu önlemek için, paylaşılan derlemeleri Genel Derleme Önbelleği'ne (GAC) yüklemeniz ve bileşen için bir MergeModule kullanmanız gerekir. Uygulamayı GAC'ye yükleyemiyorsanız, sürüme özgü bir alt dizinde CommonFilesFolder'a yüklenmelidir.

Paylaşılmayan derlemeler, çağrı uygulamasıyla dizinde yan yana bulunmalıdır.

Ayrıca bkz.