gpt4 book ai didi

c# - 如何调用基类中定义的私有(private) COM 接口(interface)的方法?

转载 作者:太空宇宙 更新时间:2023-11-03 18:32:59 24 4
gpt4 key购买 nike

如何从派生类调用基类中定义的私有(private) COM 接口(interface)的方法?

例如,这里是 COM 接口(interface),IComInterface (IDL):

[
uuid(9AD16CCE-7588-486C-BC56-F3161FF92EF2),
oleautomation
]
interface IComInterface: IUnknown
{
HRESULT ComMethod([in] IUnknown* arg);
}

这是 OldLibrary 程序集中的 C# 类 BaseClass,它像这样实现 IComInterface(注意接口(interface)声明为私有(private)):

// 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版本,因为base 的 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;
}

}
}

如何在不使用反射的情况下从 ImprovedClass.ComMethod 调用 BaseClass.ComMethod
我可以使用反射,但在实际用例 IComInterface 是一个复杂的 OLE 接口(interface),具有许多复杂签名的成员。

我认为因为 BaseClass.IComInterfaceImprovedClass.IComInterface 都是具有相同 GUID 和相同方法签名的 COM 接口(interface),并且有 COM Type Equivalence在 .NET 4.0+ 中,所以必须有一种方法可以在不考虑的情况下完成我想要的事情。

另一个要求是 ImprovedClass 必须派生自 BaseClass,因为 C# 客户端代码需要 BaseClass 的实例,它传递到 COM 客户端代码。因此,将 BaseClass 包含在 ImprovedClass 中不是一种选择。

[已编辑] 一个涉及从 WebBrowser 派生的真实场景和 WebBrowserSite描述here .

最佳答案

我习惯于在 C++ 中执行此操作,因此我在此处将 C++ 转换为 C#。 (即,您可能需要进行一些调整。)

COM identity rules要求对象上的接口(interface)集是静态的。因此,如果您可以获得一些明确由 BaseClass 实现的接口(interface),则可以 QI 关闭该接口(interface)以获取 BaseClassIComInterface 实现。

所以,像这样:

type typeBaseIComInterface = typeof(OldLibrary.BaseClass).GetInterfaces().First((t) => t.GUID == typeof(IComInterface).GUID); 
IntPtr unkBaseIComInterface = Marshal.GetComInterfaceForObject(this, typeBaseIComInterface, CustomQueryInterfaceMode.Ignore);
dynamic baseptr = Marshal.GetTypedObjectForIUnknown(unkBaseIComInterface, typeof(OldLibrary.BaseClass);
baseptr.ComMethod(/* args go here */);

关于c# - 如何调用基类中定义的私有(private) COM 接口(interface)的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19712462/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com