Jak wywołać metodę prywatnych interfejsów COM zdefiniowanych w klasie bazowej?
Jak mogę wywołać metodę prywatnego interfejsu COM, zdefiniowaną w klasie bazowej, z klasy pochodnej?
Na przykład tutaj jest interfejs COM,IComInterface
(IDL):
[
uuid(9AD16CCE-7588-486C-BC56-F3161FF92EF2),
oleautomation
]
interface IComInterface: IUnknown
{
HRESULT ComMethod([in] IUnknown* arg);
}
Oto klasa C #BaseClass
zOldLibrary
montaż, który realizujeIComInterface
tak (zauważ, że interfejs jest zadeklarowany jako prywatny):
// Assembly "OldLibrary"
public static class OldLibrary
{
[ComImport(), Guid("9AD16CCE-7588-486C-BC56-F3161FF92EF2")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IComInterface
{
void ComMethod([In, MarshalAs(UnmanagedType.Interface)] object arg);
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
public class BaseClass : IComInterface
{
void IComInterface.ComMethod(object arg)
{
Console.WriteLine("BaseClass.IComInterface.ComMethod");
}
}
}
Wreszcie, mamy ulepszoną wersję,ImprovedClass
, z którego pochodziBaseClass
, ale deklaruje i implementuje własną wersjęIComInterface
, ponieważ bazaOldLibrary.IComInterface
jest niedostępny:
// Assembly "NewLibrary"
public static class NewLibrary
{
[ComImport(), Guid("9AD16CCE-7588-486C-BC56-F3161FF92EF2")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IComInterface
{
void ComMethod([In, MarshalAs(UnmanagedType.Interface)] object arg);
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
public class ImprovedClass :
OldLibrary.BaseClass,
IComInterface,
ICustomQueryInterface
{
// IComInterface
void IComInterface.ComMethod(object arg)
{
Console.WriteLine("ImprovedClass.IComInterface.ComMethod");
// How do I call base.ComMethod here,
// otherwise than via reflection?
}
// ICustomQueryInterface
public CustomQueryInterfaceResult GetInterface(ref Guid iid, out IntPtr ppv)
{
if (iid == typeof(IComInterface).GUID)
{
ppv = Marshal.GetComInterfaceForObject(this, typeof(IComInterface), CustomQueryInterfaceMode.Ignore);
return CustomQueryInterfaceResult.Handled;
}
ppv = IntPtr.Zero;
return CustomQueryInterfaceResult.NotHandled;
}
}
}
Jak zadzwonić?BaseClass.ComMethod
zImprovedClass.ComMethod
bez refleksji?
Mogę użyć refleksji, ale w prawdziwym przypadku użyciaIComInterface
to złożony interfejs OLE z wieloma członkami złożonych podpisów.
Myślałem tak, ponieważ obojeBaseClass.IComInterface
iImprovedClass.IComInterface
są zarówno interfejsami COM z tym samym identyfikatorem GUID, jak i identycznymi sygnaturami metodRównoważność typu COM w .NET 4.0+, więc musi istnieć sposób na zrobienie tego, czego oczekuję, bez refleksji.
Innym wymogiem jest toImprovedClass
musi pochodzić odBaseClass
, ponieważ kod klienta C # oczekuje wystąpieniaBaseClass
, które przekazuje do kodu klienta COM. Tak więc, powstrzymywanieBaseClass
wewnątrzImprovedClass
nie jest opcją.
[EDITED] Scenariusz z życia codziennego, z którego wynikaWebBrowser
iWebBrowserSite
jest opisanytutaj.