Aracılığıyla paylaş


Nesneler için Varsayılan Sıralama

olarak System.Object yazılan parametreler ve alanlar, yönetilmeyen koda aşağıdaki türlerden biri olarak gösterilebilir:

  • Nesne bir parametre olduğunda bir değişken.

  • Nesne bir yapı alanı olduğunda arabirim.

Yalnızca COM birlikte çalışma, nesne türleri için sıralamayı destekler. Varsayılan davranış, nesneleri COM varyantlarına göre sıralamaktır. Bu kurallar yalnızca Object türüne uygulanır ve Object sınıfından türetilen kesin olarak belirlenmiş nesnelere uygulanmaz.

Marshalling Seçenekleri

Aşağıdaki tabloda, Nesne veri türü için sıralama seçenekleri gösterilmektedir. MarshalAsAttribute özniteliği, nesneleri sıralamak için birkaç UnmanagedType numaralandırma değeri sağlar.

Numaralandırma türü Yönetilmeyen biçimin açıklaması
UnmanagedType.Struct

(parametreler için varsayılan)
COM stili bir değişken.
UnmanagedType.Interface Mümkünse bir IDispatch arabirimi; değilse, bir IUnknown arabirimi.
UnmanagedType.IUnknown

(alanlar için varsayılan)
IUnknown arabirimi.
UnmanagedType.IDispatch IDispatch arabirimi.

Aşağıdaki örnekte için MarshalObjectyönetilen arabirim tanımı gösterilmektedir.

Interface MarshalObject
   Sub SetVariant(o As Object)
   Sub SetVariantRef(ByRef o As Object)
   Function GetVariant() As Object

   Sub SetIDispatch( <MarshalAs(UnmanagedType.IDispatch)> o As Object)
   Sub SetIDispatchRef(ByRef <MarshalAs(UnmanagedType.IDispatch)> o _
      As Object)
   Function GetIDispatch() As <MarshalAs(UnmanagedType.IDispatch)> Object
   Sub SetIUnknown( <MarshalAs(UnmanagedType.IUnknown)> o As Object)
   Sub SetIUnknownRef(ByRef <MarshalAs(UnmanagedType.IUnknown)> o _
      As Object)
   Function GetIUnknown() As <MarshalAs(UnmanagedType.IUnknown)> Object
End Interface
interface MarshalObject {
   void SetVariant(Object o);
   void SetVariantRef(ref Object o);
   Object GetVariant();

   void SetIDispatch ([MarshalAs(UnmanagedType.IDispatch)]Object o);
   void SetIDispatchRef([MarshalAs(UnmanagedType.IDispatch)]ref Object o);
   [MarshalAs(UnmanagedType.IDispatch)] Object GetIDispatch();
   void SetIUnknown ([MarshalAs(UnmanagedType.IUnknown)]Object o);
   void SetIUnknownRef([MarshalAs(UnmanagedType.IUnknown)]ref Object o);
   [MarshalAs(UnmanagedType.IUnknown)] Object GetIUnknown();
}

Aşağıdaki kod arabirimi bir tür kitaplığına aktarır MarshalObject .

interface MarshalObject {
   HRESULT SetVariant([in] VARIANT o);
   HRESULT SetVariantRef([in,out] VARIANT *o);
   HRESULT GetVariant([out,retval] VARIANT *o)
   HRESULT SetIDispatch([in] IDispatch *o);
   HRESULT SetIDispatchRef([in,out] IDispatch **o);
   HRESULT GetIDispatch([out,retval] IDispatch **o)
   HRESULT SetIUnknown([in] IUnknown *o);
   HRESULT SetIUnknownRef([in,out] IUnknown **o);
   HRESULT GetIUnknown([out,retval] IUnknown **o)
}

Not

Birlikte çalışma marshaller, çağrıdan sonra değişken içinde ayrılan tüm nesneleri otomatik olarak serbesttir.

Aşağıdaki örnekte biçimlendirilmiş bir değer türü gösterilmektedir.

Public Structure ObjectHolder
   Dim o1 As Object
   <MarshalAs(UnmanagedType.IDispatch)> Public o2 As Object
End Structure
public struct ObjectHolder {
   Object o1;
   [MarshalAs(UnmanagedType.IDispatch)]public Object o2;
}

Aşağıdaki kod, biçimlendirilmiş türü bir tür kitaplığına dışarı aktarır.

struct ObjectHolder {
   VARIANT o1;
   IDispatch *o2;
}

Nesneyi Arabirime Hazırlama

Bir nesne COM'a arabirim olarak sunulduğunda, bu arabirim yönetilen türün Object sınıf arabirimidir ( _Object arabirimi). Bu arabirim, sonuçta elde edilen tür kitaplığında IDispatch (UnmanagedType) veya IUnknown (UnmanagedType.IUnknown) olarak yazılır. COM istemcileri, yönetilen sınıfın üyelerini veya türetilmiş sınıfları tarafından uygulanan üyeleri _Object arabirimi aracılığıyla dinamik olarak çağırabilir. İstemci, yönetilen tür tarafından açıkça uygulanan diğer arabirimleri almak için QueryInterface'i de çağırabilir.

Nesneyi Çeşitlendirmeye Göre Sıralama

Bir nesne bir değişkene göre yapılandırıldığında, iç değişken türü aşağıdaki kurallara göre çalışma zamanında belirlenir:

  • Nesne başvurusu null (Visual Basic'te hiçbir şey) ise, nesne VT_EMPTY türünde bir değişkene göre gruplandırılır.

  • Nesne aşağıdaki tabloda listelenen herhangi bir türün örneğiyse, sonuçta elde edilen değişken türü, marshaller'da yerleşik olarak bulunan kurallar tarafından belirlenir ve tabloda gösterilir.

  • Sıralama davranışını açıkça denetlemesi gereken diğer nesneler arabirimi uygulayabilir IConvertible . Bu durumda, değişken türü yönteminden IConvertible.GetTypeCode döndürülen tür kodu tarafından belirlenir. Aksi takdirde, nesne VT_UNKNOWN türünde bir değişken olarak sıralanır.

Sistem Türlerini Çeşitlendirmeye Göre Sıralama

Aşağıdaki tabloda yönetilen nesne türleri ve buna karşılık gelen COM değişken türleri gösterilmektedir. Bu türler yalnızca çağrılan yöntemin imzası türünde System.Objectolduğunda dönüştürülür.

Object type COM değişken türü
Null nesne başvurusu (Visual Basic'te hiçbir şey). VT_EMPTY
System.DBNull VT_NULL
System.Runtime.InteropServices.ErrorWrapper VT_ERROR
System.Reflection.Missing E_PARAMNOTFOUND ile VT_ERROR
System.Runtime.InteropServices.DispatchWrapper VT_DISPATCH
System.Runtime.InteropServices.UnknownWrapper VT_UNKNOWN
System.Runtime.InteropServices.CurrencyWrapper VT_CY
System.Boolean VT_BOOL
System.SByte VT_I1
System.Byte VT_UI1
System.Int16 VT_I2
System.UInt16 VT_UI2
System.Int32 VT_I4
System.UInt32 VT_UI4
System.Int64 VT_I8
System.UInt64 VT_UI8
System.Single VT_R4
System.Double VT_R8
System.Decimal VT_DECIMAL
System.DateTime VT_DATE
System.String VT_BSTR
System.IntPtr VT_INT
System.UIntPtr VT_UINT
System.Array VT_ARRAY

MarshalObject Aşağıdaki kod örneği, önceki örnekte tanımlanan arabirimi kullanarak çeşitli çeşitleme türlerinin COM sunucusuna nasıl geçir yapılacağını gösterir.

Dim mo As New MarshalObject()
mo.SetVariant(Nothing)         ' Marshal as variant of type VT_EMPTY.
mo.SetVariant(System.DBNull.Value) ' Marshal as variant of type VT_NULL.
mo.SetVariant(CInt(27))        ' Marshal as variant of type VT_I2.
mo.SetVariant(CLng(27))        ' Marshal as variant of type VT_I4.
mo.SetVariant(CSng(27.0))      ' Marshal as variant of type VT_R4.
mo.SetVariant(CDbl(27.0))      ' Marshal as variant of type VT_R8.
MarshalObject mo = new MarshalObject();
mo.SetVariant(null);            // Marshal as variant of type VT_EMPTY.
mo.SetVariant(System.DBNull.Value); // Marshal as variant of type VT_NULL.
mo.SetVariant((int)27);          // Marshal as variant of type VT_I2.
mo.SetVariant((long)27);          // Marshal as variant of type VT_I4.
mo.SetVariant((single)27.0);   // Marshal as variant of type VT_R4.
mo.SetVariant((double)27.0);   // Marshal as variant of type VT_R8.

karşılık gelen yönetilen türleri olmayan COM türleri, , DispatchWrapper, UnknownWrapperve CurrencyWrappergibi ErrorWrappersarmalayıcı sınıfları kullanılarak sıralanabilir. Aşağıdaki kod örneğinde, com sunucusuna çeşitli türlerde çeşitlemeler geçirmek için bu sarmalayıcıların nasıl kullanılacağı gösterilmektedir.

Imports System.Runtime.InteropServices
' Pass inew as a variant of type VT_UNKNOWN interface.
mo.SetVariant(New UnknownWrapper(inew))
' Pass inew as a variant of type VT_DISPATCH interface.
mo.SetVariant(New DispatchWrapper(inew))
' Pass a value as a variant of type VT_ERROR interface.
mo.SetVariant(New ErrorWrapper(&H80054002))
' Pass a value as a variant of type VT_CURRENCY interface.
mo.SetVariant(New CurrencyWrapper(New Decimal(5.25)))
using System.Runtime.InteropServices;
// Pass inew as a variant of type VT_UNKNOWN interface.
mo.SetVariant(new UnknownWrapper(inew));
// Pass inew as a variant of type VT_DISPATCH interface.
mo.SetVariant(new DispatchWrapper(inew));
// Pass a value as a variant of type VT_ERROR interface.
mo.SetVariant(new ErrorWrapper(0x80054002));
// Pass a value as a variant of type VT_CURRENCY interface.
mo.SetVariant(new CurrencyWrapper(new Decimal(5.25)));

Sarmalayıcı sınıfları ad alanında System.Runtime.InteropServices tanımlanır.

IConvertible Arabirimini Varyant'a Hazırlama

Önceki bölümde listelenenler dışındaki türler, arabirimini uygulayarak IConvertible bunların nasıl sıralanmış olduğunu denetleyebilir. Nesne IConvertible arabirimini uygularsa, COM değişken türü çalışma zamanında yönteminden IConvertible.GetTypeCode döndürülen sabit listesi değeriyle TypeCode belirlenir.

Aşağıdaki tabloda TypeCode numaralandırması için olası değerler ve her değer için karşılık gelen COM değişken türü gösterilmektedir.

TypeCode COM değişken türü
TypeCode.Empty VT_EMPTY
TypeCode.Object VT_UNKNOWN
TypeCode.DBNull VT_NULL
TypeCode.Boolean VT_BOOL
TypeCode.Char VT_UI2
TypeCode.Sbyte VT_I1
TypeCode.Byte VT_UI1
TypeCode.Int16 VT_I2
TypeCode.UInt16 VT_UI2
TypeCode.Int32 VT_I4
TypeCode.UInt32 VT_UI4
TypeCode.Int64 VT_I8
TypeCode.UInt64 VT_UI8
TypeCode.Single VT_R4
TypeCode.Double VT_R8
TypeCode.Decimal VT_DECIMAL
TypeCode.DateTime VT_DATE
TypeCode.String VT_BSTR
Desteklenmiyor. VT_INT
Desteklenmiyor. VT_UINT
Desteklenmiyor. VT_ARRAY
Desteklenmiyor. VT_RECORD
Desteklenmiyor. VT_CY
Desteklenmiyor. VT_VARIANT

COM değişkeninin değeri, IConvertible.To Türü arabirimi çağrılarak belirlenir; burada Tür, IConvertible.GetTypeCode'dan döndürülen türe karşılık gelen dönüştürme yordamıdır. Örneğin, IConvertible.GetTypeCode'dan TypeCode.Double döndüren bir nesne, VT_R8 türünde bir COM değişkeni olarak sıralanır. Değişken değerini (COM değişkeninin dblVal alanında depolanır) IConvertible arabirimine dönüştürerek ve yöntemini çağırarak ToDouble elde edebilirsiniz.

Varyantı Nesneye Göre Sıralama

Bir varyantı bir nesneye sıralarken, sıralanmış değişkenin türü ve bazen değeri, üretilen nesnenin türünü belirler. Aşağıdaki tabloda, com'dan .NET Framework'e bir değişken geçirildiğinde m marshallerreates tarafından belirlenen her değişken türü ve ilgili nesne türü tanımlanmaktadır.

COM değişken türü Object type
VT_EMPTY Null nesne başvurusu (Visual Basic'te hiçbir şey).
VT_NULL System.DBNull
VT_DISPATCH System.__ComObject veya null if (pdispVal == null)
VT_UNKNOWN System.__ComObject veya null if (punkVal == null)
VT_ERROR System.UInt32
VT_BOOL System.Boolean
VT_I1 System.SByte
VT_UI1 System.Byte
VT_I2 System.Int16
VT_UI2 System.UInt16
VT_I4 System.Int32
VT_UI4 System.UInt32
VT_I8 System.Int64
VT_UI8 System.UInt64
VT_R4 System.Single
VT_R8 System.Double
VT_DECIMAL System.Decimal
VT_DATE System.DateTime
VT_BSTR System.String
VT_INT System.Int32
VT_UINT System.UInt32
| VT_ARRAY VT_* System.Array
VT_CY System.Decimal
VT_RECORD Karşılık gelen kutulanmış değer türü.
VT_VARIANT Desteklenmiyor.

COM'dan yönetilen koda ve ardından COM'a geri geçirilen değişken türleri, çağrı süresi boyunca aynı değişken türünü koruyamayabilir. COM'dan .NET Framework'e VT_DISPATCH türünde bir değişken geçirildiğinde ne olacağını düşünün. Sıralama sırasında, değişken bir System.Objectöğesine dönüştürülür. Nesne daha sonra COM'a geri geçirilirse, VT_UNKNOWN türündeki bir değişkene geri döner. Bir nesne yönetilen koddan COM'a sıralandığında üretilen değişkenin ilk olarak nesneyi üretmek için kullanılan değişkenle aynı türde olacağının garantisi yoktur.

ByRef Değişkenlerini Sıralama

Değişkenlerin kendileri değere veya başvuruya göre geçirilse de, VT_BYREF bayrağı değişken içeriğinin değer yerine başvuruyla geçirildiğini belirtmek için herhangi bir değişken türüyle de kullanılabilir. Başvuruya göre varyantları sıralama ve VT_BYREF bayrak kümesiyle bir değişken hazırlama arasındaki fark kafa karıştırıcı olabilir. Aşağıdaki çizimde farklar açıklanır:

Yığında geçirilen değişkeni gösteren diyagram. Değere ve başvuruya göre geçirilen çeşitlemeler

Nesneleri ve değişkenleri değere göre sıralamak için varsayılan davranış

  • Nesneleri yönetilen koddan COM'a geçirirken, nesnenin içeriği, Marshalling Object to Variant içinde tanımlanan kurallar kullanılarak, marshaller tarafından oluşturulan yeni bir değişkene kopyalanır. Yönetilmeyen taraftaki değişkende yapılan değişiklikler, çağrıdan döndürüldüklerinde özgün nesneye geri yayılmaz.

  • VARYantları COM'dan yönetilen koda geçirirken, varyantın içeriği Yeni oluşturulan bir nesneye kopyalanır ve Çeşitleme Değişkenini Nesneye Sıralama'da tanımlanan kurallar kullanılır. Yönetilen taraftaki nesnede yapılan değişiklikler, çağrıdan sonra özgün değişkene geri yayılmaz.

Başvuruya göre nesneleri ve değişkenleri sıralamak için varsayılan davranış

Değişiklikleri çağırana geri yaymak için parametrelerin başvuruya göre geçirilmesi gerekir. Örneğin, başvuruya göre parametreleri geçirmek için C# dilinde (veya Visual Basic yönetilen kodunda ByRef) ref anahtar sözcüğünü kullanabilirsiniz. COM'da başvuru parametreleri değişken * gibi bir işaretçi kullanılarak geçirilir.

  • Bir nesneyi başvuruya göre COM'a geçirirken, marshaller yeni bir değişken oluşturur ve çağrı yapılmadan önce nesne başvurusunun içeriğini değişkene kopyalar. Değişken, kullanıcının değişkenin içeriğini değiştirmekte serbest olduğu yönetilmeyen işleve geçirilir. Çağrıdan sonra, yönetilmeyen tarafındaki değişkende yapılan tüm değişiklikler özgün nesneye geri yayılır. Değişkenin türü çağrıya geçirilen değişkenin türünden farklıysa, değişiklikler farklı türde bir nesneye geri yayılır. Yani, çağrıya geçirilen nesnenin türü, çağrıdan döndürülen nesnenin türünden farklı olabilir.

  • Başvuruya göre yönetilen koda bir değişken geçirirken, marshaller yeni bir nesne oluşturur ve çağrıyı yapmadan önce değişkenin içeriğini nesneye kopyalar. Nesneye başvuru yönetilen işleve geçirilir ve burada kullanıcı nesneyi değiştirebilir. Çağrıdan döndürülen, başvurulan nesnede yapılan tüm değişiklikler özgün varyanta geri yayılır. Nesnenin türü çağrıya geçirilen nesnenin türünden farklıysa, özgün değişkenin türü değiştirilir ve değer değişkene geri yayılır. Yine, çağrıya geçirilen değişkenin türü, çağrıdan döndürülen değişkenin türünden farklı olabilir.

VT_BYREF bayrağı ayarlanmış bir değişken için varsayılan sıralama davranışı

  • Yönetilen koda değere göre geçirilen bir değişkende, değişkenin değer yerine başvuru içerdiğini belirtmek için VT_BYREF bayrağı ayarlanabilir. Bu durumda, değişken değere göre geçirildiği için değişken yine de bir nesneye göre sıraya alınır. Marshaller, değişkenin içeriğini otomatik olarak başvurur ve çağrıyı yapmadan önce yeni oluşturulan bir nesneye kopyalar. Nesne daha sonra yönetilen işleve geçirilir; ancak, çağrısından döndürülen nesne özgün değişkene geri yayılmaz. Yönetilen nesnede yapılan değişiklikler kaybolur.

    Dikkat

    Değişkende VT_BYREF bayrağı ayarlanmış olsa bile, değer tarafından geçirilen bir değişkenin değerini değiştirmenin hiçbir yolu yoktur.

  • Yönetilen koda başvuruyla geçirilen bir değişken, değişkenin başka bir başvuru içerdiğini belirtmek için VT_BYREF bayrağını da ayarlayabilir. Bunu yaparsa, değişken başvuruyla geçirildiğinden, değişken bir başvuru nesnesine göre sıraya alınır. Marshaller, değişkenin içeriğini otomatik olarak başvurur ve çağrıyı yapmadan önce yeni oluşturulan bir nesneye kopyalar. Çağrısından döndürülen nesnenin değeri, yalnızca nesne geçirilen nesneyle aynı türdeyse özgün değişken içindeki başvuruya geri yayılır. Yani yayma, VT_BYREF bayrağı ayarlanmış bir değişkenin türünü değiştirmez. Nesnenin türü çağrı sırasında değiştirilirse, çağrıdan döndürülerek bir InvalidCastException gerçekleşir.

Aşağıdaki tabloda, çeşitlemeler ve nesneler için yayma kuralları özetlemektedir.

Kaynak Amaç Geri yayılan değişiklikler
Değişken v Nesne o Asla
Nesne o Değişken v Asla
Değişken * bd Başvuru Nesnesi o Her zaman
Başvuru nesnesi o Değişken * bd Her zaman
Variant v (VT_BYREF | VT_*) Nesne o Asla
Variant v (VT_BYREF | VT_) Başvuru Nesnesi o Yalnızca tür değişmediyse.

Ayrıca bkz.