2010-06-01 7 views
5

Próbuję zrozumieć, co jest poprawne, dlaczego zaimplementować interfejsy COM z kodu C#. Jest to proste, gdy interfejs nie dziedziczy z innego interfejsu bazowego. Podobnie jak ten:Jak zadeklarować i zaimplementować interfejs COM w C#, który dziedziczy z innego interfejsu COM?

Jednak rzeczy zaczynają być zmęczone, kiedy muszę zaimplementować interfejs, który dziedziczy z innych interfejsów COM. Na przykład, jeśli zaimplementować interfejs IPersistFolder2 która dziedziczy z IPersistFolder która dziedziczy z IPersist jak zwykle na kod 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); 
} 

System operacyjny nie jest w stanie wywołać metody na mój obiekt realizacji. Podczas debugowania widzę, że konstruktor mojej implementacji IPersistFolder2 jest wywoływany wiele razy, jednak metody interfejsu, które zaimplementowałem, nie są wywoływane. Ja realizacji IPersistFolder2 następująco:

[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) { ... } 
} 

Co dziwne, kiedy Oświadczam importu interfejsu COM następujące, to działa:

[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); 
} 

Nie wiem, dlaczego to działa, kiedy deklaruj interfejsy COM w ten sposób (ukrywaj bazowe metody interfejsu za pomocą new). Być może jest to związane ze sposobem działania IUnknown. Czy ktoś wie, jaki jest prawidłowy sposób implementacji interfejsów COM w C#, który dziedziczy z innych interfejsów COM i dlaczego?

+0

Głosowanie za pokazanie mi, jak "importować" IPersist. http://stackoverflow.com/questions/1253368/c-get-progid-from-com-object używa go, ale nie wspomina, jak dodać do niego odnośnik. –

+0

Wpadłem na ten sam problem i udało mi się go naprawić za pomocą słowa kluczowego "new". Dzięki @Hans Passant aswell :) –

Odpowiedz

3

Dobra sztuczka z nowym słowem kluczowym, które naprawiłoby problem. Problem polega na tym, że COM nie obsługuje dziedziczenia. Jest to po prostu wygoda notacji w IDL, aby wyglądało tak, jak robi. W rzeczywistości interfejs v-table musi agregować wszystkie "odziedziczone" interfejsy podstawowe. Innymi słowy, w przypadku interfejsu IPersistFolder musi on replikować gniazda v-table dla 3 nieznanych metod i metody IPersist :: GetClassID. CLR zajmuje się IUnknown btw.

Tablica v, którą kompilacja .NET nie jest zgodna z tym układem, nie replikuje gniazd metod metod klasy podstawowej.