如何从派生类调用在基类中定义的私有 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.IComInterface
COM 接口,具有相同的 GUID 和相同的方法签名,并且 .NET 4.0+ 中存在COM 类型等效,所以必须有一种方法可以在没有反射的情况下完成我所追求的事情。
另一个要求是ImprovedClass
必须从 派生BaseClass
,因为 C# 客户端代码需要一个 的实例BaseClass
,并将其传递给 COM 客户端代码。因此,BaseClass
内部遏制ImprovedClass
不是一种选择。
[已编辑]一个真实的场景,其中涉及衍生WebBrowser
并在此处WebBrowserSite
进行了描述。