Gibt es einen Zweck von ComDefaultInterface für einen COM Callable Wrapper?

Was ist der Zweck vonComDefaultInterfaceAttribute Attribut, wenn das verwaltete Objekt mitClassInterfaceType.None wird gemarshallt entwederIUnknown oderIDispatch, sowieso?

Betrachten Sie die folgende C # -KlasseAuthenticateHelper, das COM implementiertIAuthenticate:

[ComImport]
[Guid("79eac9d0-baf9-11ce-8c82-00aa004ba90b")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IAuthenticate
{
    [PreserveSig]
    int Authenticate(
        [In, Out] ref IntPtr phwnd,
        [In, Out, MarshalAs(UnmanagedType.LPWStr)] ref string pszUsername,
        [In, Out, MarshalAs(UnmanagedType.LPWStr)] ref string pszPassword);
}

[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[ComDefaultInterface(typeof(IAuthenticate))]
public class AuthenticateHelper: IAuthenticate
{
    public int Authenticate(ref IntPtr phwnd, ref string pszUsername, ref string pszPassword)
    {
        phwnd = IntPtr.Zero;
        pszUsername = String.Empty;
        pszPassword = String.Empty;
        return 0;
    }
}    

Ich habe gerade erfahren, dass .NET Interop Runtime die Implementierung von trenntIUnknown vonIAuthenticate für eine solche Klasse:

AuthenticateHelper ah = new AuthenticateHelper();
IntPtr unk1 = Marshal.GetComInterfaceForObject(ah, typeof(IAuthenticate));
IntPtr unk2 = Marshal.GetIUnknownForObject(ah);
Debug.Assert(unk1 == unk2); // will assert!

Das habe ich bei der Implementierung gelerntIServiceProvder, daFolgendes hat nicht funktioniertstürzte es im Client-Code bei der Rückkehr von abQueryService:

[ComImport]
[Guid("6d5140c1-7436-11ce-8034-00aa006009fa")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IServiceProvider
{
    [PreserveSig]
    int QueryService(
        [In] ref Guid guidService,
        [In] ref Guid riid,
        [Out, MarshalAs(UnmanagedType.Interface, IidParameterIndex=1)] out object ppvObject    
}

// ...

public readonly Guid IID_IUnknown = new Guid("00000000-0000-0000-C000-000000000046");

AuthenticateHelper ah = new AuthenticateHelper();

int IServiceProvider.QueryService(ref Guid guidService, ref Guid riid, out object ppvObject)
{
    if (guidService == typeof(IAuthenticate).GUID && (riid == IID_IUnknown || riid == guidService))
    {
        ppvObject = this.ah; // same as ppvObject = (IAuthenticate)this.ah
        return S_OK;
    }
    ppvObject = null;
    return E_NOINTERFACE;
}

Ich erwartete naiv die Instanz vonAuthenticateHelper würde gemarshallt werden alsIAuthenticate weil die klasse deklariert[ComDefaultInterface(typeof(IAuthenticate))], soIAuthenticate ist die einzige und die Standard-COM-Schnittstelle von dieser Klasse implementiert. Das funktionierte jedoch nicht, offensichtlich, weil das Objekt immer noch als gemarshallt wirdIUnknown.

Folgendes funktioniert, aber es ändert die Signatur vonQueryService und macht es weniger benutzerfreundlich, um Objekte zu konsumieren (anstatt bereitzustellen):

[ComImport]
[Guid("6d5140c1-7436-11ce-8034-00aa006009fa")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IServiceProvider
{
    [PreserveSig]
    int QueryService(
        [In] ref Guid guidService,
        [In] ref Guid riid,
        [Out] out IntPtr ppvObject);
}

// ...

int IServiceProvider.QueryService(ref Guid guidService, ref Guid riid, out IntPtr ppvObject)
{
    if (guidService == typeof(IAuthenticate).GUID && (riid == IID_IUnknown || riid == guidService))
    {
        ppvObject = Marshal.GetComInterfaceForObject(this.ah, typeof(IAuthenticate));
        return S_OK;
    }
    ppvObject = IntPtr.Zero;
    return E_NOINTERFACE;
}

Also, warum sollte ich angebenComDefaultInterface überhaupt, wenn es das Marshalling nicht beeinflusst? Die einzige andere Verwendung, die ich sehe, ist die Generierung von Typbibliotheken.

Es ist nicht verwalteter Client-COM-Code, der meine verwaltete Implementierung von aufruftIServiceProvider::QueryService. Gibt es einen Weg zu machenQueryService arbeite in meinem beispiel ohne auf low-level sachen wie zuzugreifenGetComInterfaceForObject?

Antworten auf die Frage(1)

Ihre Antwort auf die Frage