System.Runtime.InteropServices.ICustomMarshaler arabirimi

Bu makale, bu API'nin başvuru belgelerine ek açıklamalar sağlar.

Arabirimi, ICustomMarshaler yöntem çağrılarını işlemek için özel sarmalayıcılar sağlar.

Bir marshaller, eski ve yeni arabirimlerin işlevselliği arasında bir köprü sağlar. Özel hazırlama aşağıdaki avantajları sağlar:

  • Eski bir arabirimle çalışacak şekilde tasarlanmış istemci uygulamalarının yeni bir arabirim uygulayan sunucularla da çalışmasını sağlar.
  • Yeni bir arabirimle çalışacak şekilde derlenen istemci uygulamalarının eski bir arabirim uygulayan sunucularla çalışmasını sağlar.

Farklı sıralama davranışı tanıtır veya Bileşen Nesne Modeli'ne (COM) farklı bir şekilde kullanıma sunulan bir arabiriminiz varsa, birlikte çalışma marshaller'ını kullanmak yerine özel bir marshaller tasarlayabilirsiniz. Özel bir marshaller kullanarak yeni .NET Framework bileşenleriyle mevcut COM bileşenleri arasındaki ayrımı en aza indirebilirsiniz.

Örneğin, adlı INewbir yönetilen arabirim geliştirdiğinizi varsayalım. Bu arabirim, standart bir COM çağrılabilen sarmalayıcı (CCW) aracılığıyla COM'a sunulduğunda, yönetilen arabirimle aynı yöntemlere sahiptir ve birlikte çalışma marshaller'ını oluşturan sıralama kurallarını kullanır. Şimdi adlı IOld iyi bilinen bir COM arabiriminin arabirimle aynı işlevselliği sağladığını INew varsayalım. Özel bir marshaller tasarlayarak, yalnızca çağrıları arabirimin IOld yönetilen uygulamasına temsilci olarak veren yönetilmeyen bir uygulaması INew sağlayabilirsiniz. Bu nedenle, özel marshaller yönetilen ve yönetilmeyen arabirimler arasında bir köprü işlevi görür.

Not

Yönetilen koddan yalnızca dağıtım arabirimindeki yönetilmeyen koda çağrılırken özel marshallers çağrılmaz.

Hazırlama türünü tanımlama

Özel bir marshaller oluşturabilmeniz için önce, sıralanacak yönetilen ve yönetilmeyen arabirimleri tanımlamanız gerekir. Bu arabirimler genellikle aynı işlevi gerçekleştirir ancak yönetilen ve yönetilmeyen nesnelere farklı şekilde sunulur.

Yönetilen derleyici meta verilerden yönetilen bir arabirim oluşturur ve sonuçta elde edilen arabirim diğer yönetilen arabirimlere benzer. Aşağıdaki örnekte tipik bir arabirim gösterilmektedir.

public interface INew
{
    void NewMethod();
}
Public Interface INew
    Sub NewMethod()
End Interface

Yönetilmeyen türü Arabirim Tanım Dili'nde (IDL) tanımlar ve Microsoft Arabirim Tanım Dili (MIDL) derleyicisi ile derlersiniz. Aşağıdaki örnekte gösterildiği gibi, bir kitaplık deyimi içinde arabirimi tanımlar ve evrensel benzersiz tanımlayıcı (UUID) özniteliğine sahip bir arabirim kimliği atarsınız.

 [uuid(9B2BAADA-0705-11D3-A0CD-00C04FA35826)]
library OldLib {
     [uuid(9B2BAADD-0705-11D3-A0CD-00C04FA35826)]
     interface IOld : IUnknown
         HRESULT OldMethod();
}

MIDL derleyicisi birkaç çıkış dosyası oluşturur. Arabirim Old.idl içinde tanımlanmışsa, Old_i.c çıkış dosyası aşağıdaki örnekte gösterildiği gibi arabirimin arabirim tanımlayıcısı (IID) ile bir const değişken tanımlar.

const IID IID_IOld = {0x9B2BAADD,0x0705,0x11D3,{0xA0,0xCD,0x00,0xC0,0x4F,0xA3,0x58,0x26}};

Old.h dosyası da MIDL tarafından oluşturulur. C++ kaynak kodunuzda yer alan arabirimin C++ tanımını içerir.

ICustomMarshaler arabirimini uygulama

Özel marshaller'ınız, çalışma zamanına ICustomMarshaler uygun sarmalayıcıları sağlamak için arabirimini uygulamalıdır.

Aşağıdaki C# kodu, tüm özel marshallers tarafından uygulanması gereken temel arabirimi görüntüler.

public interface ICustomMarshaler
{
    Object MarshalNativeToManaged(IntPtr pNativeData);
    IntPtr MarshalManagedToNative(Object ManagedObj);
    void CleanUpNativeData(IntPtr pNativeData);
    void CleanUpManagedData(Object ManagedObj);
    int GetNativeDataSize();
}
Public Interface ICustomMarshaler
     Function MarshalNativeToManaged( pNativeData As IntPtr ) As Object
     Function MarshalManagedToNative( ManagedObj As Object ) As IntPtr
     Sub CleanUpNativeData( pNativeData As IntPtr )
     Sub CleanUpManagedData( ManagedObj As Object )
     Function GetNativeDataSize() As Integer
End Interface

Arabirim, ICustomMarshaler dönüştürme desteği, temizleme desteği ve sıralanacak veriler hakkında bilgi sağlayan yöntemler içerir.

İşlem türü ICustomMarshaler yöntemi Açıklama
Dönüştürme (yerel koddan yönetilen koda) MarshalNativeToManaged Yerel verilere yönelik bir işaretçiyi yönetilen bir nesneye sıralar. Bu yöntem, bağımsız değişken olarak geçirilen yönetilmeyen arabirimi sıralayan özel bir çalışma zamanı çağrılabilen sarmalayıcı (RCW) döndürür. Marshaller, bu tür için özel RCW örneğini döndürmelidir.
Dönüştürme (yönetilen koddan yerel koda) MarshalManagedToNative Yönetilen nesneyi yerel verilere yönelik bir işaretçiye göre sıralar. Bu yöntem, bağımsız değişken olarak geçirilen yönetilen arabirimi sıralayan özel bir COM çağrılabilen sarmalayıcı (CCW) döndürür. Marshaller, bu tür için özel CCW örneğini döndürmelidir.
Temizleme (yerel koddan) CleanUpNativeData Marshaller'ın yöntemi tarafından döndürülen yerel verileri (CCW) temizlemesini MarshalManagedToNative sağlar.
Temizleme (yönetilen koddan) CleanUpManagedData Marshaller'ın yöntemi tarafından döndürülen yönetilen verileri (RCW) temizlemesini MarshalNativeToManaged sağlar.
Bilgi (yerel kod hakkında) GetNativeDataSize Sıralanacak yönetilmeyen verilerin boyutunu döndürür.

Dönüştürme

ICustomMarshaler.MarshalNativeToManaged

Yerel verilere yönelik bir işaretçiyi yönetilen bir nesneye sıralar. Bu yöntem, bağımsız değişken olarak geçirilen yönetilmeyen arabirimi sıralayan özel bir çalışma zamanı çağrılabilen sarmalayıcı (RCW) döndürür. Marshaller, bu tür için özel RCW örneğini döndürmelidir.

ICustomMarshaler.MarshalManagedToNative

Yönetilen nesneyi yerel verilere yönelik bir işaretçiye göre sıralar. Bu yöntem, bağımsız değişken olarak geçirilen yönetilen arabirimi sıralayan özel bir COM çağrılabilen sarmalayıcı (CCW) döndürür. Marshaller, bu tür için özel CCW örneğini döndürmelidir.

Temizleme

ICustomMarshaler.CleanUpNativeData

Marshaller'ın yöntemi tarafından döndürülen yerel verileri (CCW) temizlemesini MarshalManagedToNative sağlar.

ICustomMarshaler.CleanUpManagedData

Marshaller'ın yöntemi tarafından döndürülen yönetilen verileri (RCW) temizlemesini MarshalNativeToManaged sağlar.

Boyut bilgileri

ICustomMarshaler.GetNativeDataSize

Sıralanacak yönetilmeyen verilerin boyutunu döndürür.

Not

Özel bir marshaller, yerelden yönetilene veya temizleme işlemine sıralarken son P/Invoke hatasını ayarlayan yöntemleri çağırırsa, tarafından Marshal.GetLastWin32Error() döndürülen değer ve Marshal.GetLastPInvokeError() , hazırlama veya temizleme çağrılarındaki çağrıyı temsil eder. Bu, P/Invokes ile özel marshaller'ları DllImportAttribute.SetLastError olarak ayarlandığında hataların kaçırılmasına trueneden olabilir. Son P/Invoke hatasını korumak için uygulamadaki ICustomMarshaler ve Marshal.SetLastPInvokeError(Int32) yöntemlerini kullanınMarshal.GetLastPInvokeError().

GetInstance yöntemini uygulama

Arabirimi uygulamaya ICustomMarshaler ek olarak, özel marshallers parametresi olarak kabul eden String ve dönüş türüne ICustomMarshalersahip adlı GetInstance bir yöntem uygulamalıdırstatic. Bu static yöntem, özel bir marshaller örneğini başlatmak için ortak dil çalışma zamanının COM birlikte çalışma katmanı tarafından çağrılır. geçirilen GetInstance dize, yöntemin döndürülen özel marshaller'ı özelleştirmek için kullanabileceği bir tanımlama bilgisidir. Aşağıdaki örnekte en az ama eksiksiz ICustomMarshaler bir uygulama gösterilmektedir.

public class NewOldMarshaler : ICustomMarshaler
{
    public static ICustomMarshaler GetInstance(string pstrCookie)
        => new NewOldMarshaler();

    public Object MarshalNativeToManaged(IntPtr pNativeData) => throw new NotImplementedException();
    public IntPtr MarshalManagedToNative(Object ManagedObj) => throw new NotImplementedException();
    public void CleanUpNativeData(IntPtr pNativeData) => throw new NotImplementedException();
    public void CleanUpManagedData(Object ManagedObj) => throw new NotImplementedException();
    public int GetNativeDataSize() => throw new NotImplementedException();
}

MarshalAsAttribute Uygulama

Özel bir marshaller kullanmak için, özniteliğini MarshalAsAttribute sıralanan parametreye veya alana uygulamanız gerekir.

Ayrıca numaralandırma değerini oluşturucuya MarshalAsAttribute geçirmeniz UnmanagedType.CustomMarshaler gerekir. Ayrıca, alanı aşağıdaki adlandırılmış parametrelerden biriyle belirtmeniz MarshalType gerekir:

  • MarshalType (gerekli): Özel marshaller'ın derleme nitelikli adı. Ad, özel marshaller'ın ad alanını ve sınıfını içermelidir. Özel marshaller içinde kullanıldığı derlemede tanımlanmamışsa, tanımlandığı derlemenin adını belirtmeniz gerekir.

    Not

    Alanı yerine MarshalType alanını kullanabilirsinizMarshalTypeRef. MarshalTypeRef daha kolay belirtilmesi gereken bir tür alır.

  • MarshalCookie (isteğe bağlı): Özel marshaller'a geçirilen bir tanımlama bilgisi. Tanımlama bilgisini, marshaller'a ek bilgi sağlamak için kullanabilirsiniz. Örneğin, aynı marshaller bir dizi sarmalayıcı sağlamak için kullanılırsa, tanımlama bilgisi belirli bir sarmalayıcıyı tanımlar. Tanımlama bilgisi, marshaller yöntemine geçirilir GetInstance .

MarshalAsAttribute özniteliği, uygun sarmalayıcıyı etkinleştirebilmesi için özel marshaller'ı tanımlar. Daha sonra ortak dil çalışma zamanının birlikte çalışma hizmeti özniteliğini inceler ve bağımsız değişkenin (parametre veya alan) ilk kez sıralanması gerektiğinde özel marshaller'ı oluşturur.

Çalışma zamanı, çağrıyı MarshalNativeToManaged işlemek üzere doğru sarmalayıcıyı etkinleştirmek için özel marshaller'da ve MarshalManagedToNative yöntemlerini çağırır.

Özel bir marshaller kullanma

Özel marshaller tamamlandığında, bunu belirli bir tür için özel sarmalayıcı olarak kullanabilirsiniz. Aşağıdaki örnekte yönetilen arabirimin tanımı gösterilmektedir IUserData :

interface IUserData
{
    void DoSomeStuff(INew pINew);
}
Public Interface IUserData
    Sub DoSomeStuff(pINew As INew)
End Interface

Aşağıdaki örnekte arabirim, IUserData yönetilmeyen istemci uygulamalarının NewOldMarshaler yöntemine bir IOld arabirim DoSomeStuff geçirmesini sağlamak için özel marshaller'ı kullanır. Yöntemin DoSomeStuff yönetilen açıklaması, önceki örnekte gösterildiği gibi bir INew arabirim alırken, yönetilmeyen sürümü DoSomeStuff aşağıdaki örnekte gösterildiği gibi bir IOld arabirim işaretçisi alır.

[uuid(9B2BAADA-0705-11D3-A0CD-00C04FA35826)]
library UserLib {
     [uuid(9B2BABCD-0705-11D3-A0CD-00C04FA35826)]
     interface IUserData : IUnknown
         HRESULT DoSomeStuff(IUnknown* pIOld);
}

Yönetilen tanımını dışarı aktararak oluşturulan tür kitaplığı, standart tanım IUserData yerine bu örnekte gösterilen yönetilmeyen tanımı verir. Yönteminin MarshalAsAttributeINew yönetilen tanımında DoSomeStuff bağımsız değişkene uygulanan öznitelik, aşağıdaki örnekte gösterildiği gibi bağımsız değişkenin özel bir marshaller kullandığını gösterir.

using System.Runtime.InteropServices;
Imports System.Runtime.InteropServices
interface IUserData
{
    void DoSomeStuff(
        [MarshalAs(UnmanagedType.CustomMarshaler,
         MarshalType="NewOldMarshaler")]
    INew pINew
    );
}
Public Interface IUserData
    Sub DoSomeStuff( _
        <MarshalAs(UnmanagedType.CustomMarshaler, _
        MarshalType := "MyCompany.NewOldMarshaler")> pINew As INew)
End Interface

Önceki örneklerde, özniteliğine MarshalAsAttribute sağlanan ilk parametre numaralandırma değeridir UnmanagedType.CustomMarshalerUnmanagedType.CustomMarshaler.

İkinci parametre, özel marshaller'ın derleme nitelikli adını sağlayan alanıdır MarshalType . Bu ad, özel marshallerMarshalType="MyCompany.NewOldMarshaler" () ad alanı ve sınıfından oluşur.