2010-06-01 29 views
5

Estoy tratando de entender cuál es el motivo correcto para implementar interfaces COM a partir del código C#. Es sencillo cuando la interfaz no hereda de otra interfaz base. Como éste:¿Cómo declarar e implementar una interfaz COM en C# que hereda de otra interfaz COM?

[ComImport, Guid("2047E320-F2A9-11CE-AE65-08002B2E1262"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
public interface IShellFolderViewCB 
{ 
    long MessageSFVCB(uint uMsg, int wParam, int lParam); 
} 

Sin embargo las cosas empiezan a ser weired cuando necesito para implementar una interfaz que hereda de otras interfaces COM. Por ejemplo, si implementan la interfaz IPersistFolder2 que hereda de IPersistFolder que hereda de IPersist, ya que normalmente el código C#:

[ComImport, Guid("0000010c-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
public interface IPersist 
{ 
    void GetClassID([Out] out Guid classID); 
} 

[ComImport, Guid("000214EA-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
public interface IPersistFolder : IPersist 
{ 
    void Initialize([In] IntPtr pidl); 
} 

[ComImport, Guid("1AC3D9F0-175C-11d1-95BE-00609797EA4F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
public interface IPersistFolder2 : IPersistFolder 
{ 
    void GetCurFolder([Out] out IntPtr ppidl); 
} 

El sistema operativo no es capaz de llamar a los métodos de mi implementación del objeto. Cuando estoy depurando puedo ver que el constructor de mi implementación IPersistFolder2 se llama muchas veces, sin embargo, no se invocan los métodos de interfaz que he implementado. Estoy poniendo en práctica la IPersistFolder2 de la siguiente manera:

[Guid("A4603CDB-EC86-4E40-80FE-25D5F5FA467D")] 
public class PersistFolder: IPersistFolder2 
{ 
    void IPersistFolder2.GetClassID(ref Guid classID) { ... } 
    void IPersistFolder2.Initialize(IntPtr pidl) { ... } 
    void IPersistFolder2.GetCurFolder(out IntPtr ppidl) { ... } 
} 

Lo que parece extraño es cuando declaro las importaciones de interfaz COM de la siguiente manera, funciona:

[ComImport, Guid("0000010c-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
internal interface IPersist 
{ 
    void GetClassID([Out] out Guid classID); 
} 

[ComImport, Guid("000214EA-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
internal interface IPersistFolder : IPersist 
{ 
    new void GetClassID([Out] out Guid classID); 
    void Initialize([In] IntPtr pidl); 
} 

[ComImport, Guid("1AC3D9F0-175C-11d1-95BE-00609797EA4F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
internal interface IPersistFolder2 : IPersistFolder 
{ 
    new void GetClassID([Out] out Guid classID); 
    new void Initialize([In] IntPtr pidl); 
    void GetCurFolder([Out] out IntPtr ppidl); 
} 

No sé por qué funciona cuando declare las interfaces COM de esa manera (ocultando los métodos de interfaz base usando new). Quizás esté relacionado con la forma en que funciona IUnknown. ¿Alguien sabe cuál es la forma correcta de implementar interfaces COM en C# que hereda de otras interfaces COM y por qué?

+0

Votando por mostrarme cómo "importar" IPersist. http://stackoverflow.com/questions/1253368/c-get-progid-from-com-object lo usa pero no menciona cómo agregarle una referencia. –

+0

Me encontré con el mismo problema y pude solucionarlo con la palabra clave 'nueva'. Gracias a @Hans Passant también :) –

Respuesta

3

Buen truco con la nueva palabra clave, eso sin duda solucionó el problema. El problema aquí es que COM no admite herencia. Es simplemente la conveniencia de la notación en IDL para que parezca. En realidad, una tabla v de interfaz debe agregar todas las interfaces base "heredadas". En otras palabras, para la interfaz IPersistFolder, debe replicar los slots de la tabla v para los 3 métodos IUnknown y el método IPersist :: GetClassID. El CLR se ocupa de IUnknown por cierto.

La v-table que construye .NET no es compatible con este diseño, no replica las ranuras de método de clase base.

Cuestiones relacionadas