如何从派生类调用在基类中定义的私有 COM 接口的方法?
例如,这里是 COM 接口,IComInterface(IDL):
[
uuid(9AD16CCE-7588-486C-BC56-F3161FF92EF2),
oleautomation
]
interface IComInterface: IUnknown
{
HRESULT ComMethod([in] IUnknown* arg);
}
BaseClass这是来自程序集的 C# 类OldLibrary,它的实现IComInterface方式如下(注意接口被声明为私有):
// 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");
}
}
}
最后,这是一个改进的版本,ImprovedClass它派生自BaseClass,但声明并实现了自己的版本IComInterface,因为基础OldLibrary.IComInterface是不可访问的:
// 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;
}
}
}
我如何BaseClass.ComMethod在ImprovedClass.ComMethod没有反射的情况下打电话?
我可以使用反射,但在实际用例IComInterface中是一个复杂的 OLE 接口,其中包含许多复杂签名的成员。
我认为因为两者BaseClass.IComInterface都是ImprovedClass.IComInterfaceCOM 接口,具有相同的 GUID 和相同的方法签名,并且 .NET 4.0+ 中存在COM 类型等效,所以必须有一种方法可以在没有反射的情况下完成我所追求的事情。
另一个要求是ImprovedClass必须从 派生BaseClass,因为 C# 客户端代码需要一个 的实例BaseClass,并将其传递给 COM 客户端代码。因此,BaseClass内部遏制ImprovedClass不是一种选择。
[已编辑]一个真实的场景,其中涉及衍生WebBrowser并在此处WebBrowserSite进行了描述。