在C#中实例化托管COM对象

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在C#中实例化托管COM对象相关的知识,希望对你有一定的参考价值。

我编写了几个纯.NET DirectShow过滤器(它们是变换过滤器)并通过regasm注册它们。 GraphStudioNext使用它们没有问题。

我的问题是当我的C#应用​​程序尝试使用过滤器时 - 我必须让.NET将COM对象实例化为COM对象而不是托管的dotnet对象。这是因为我已经实现了一个过滤器选择实用程序(比如GraphStudioNext的列表功能中的插入过滤器),我无法在编译时添加对程序集的引用 - 有人可以使用自己的ComImport编写自定义.NET DirectShow过滤器'ed IBaseFilter。当我的代码尝试将类型转换为IBaseFilter时,即使他们的IBaseFilter和我的IBaseFilter共享相同的Guid,这也会导致问题。作为COM对象,这没有问题。作为.NET对象,它们实际上是不同的类型。

假设有人想在C#中编写GraphStudioNext并使其与纯.NET DirectShow过滤器一起使用 - 这甚至可能吗?

答案

一个好问题。我处理了一个类似的问题here。实际上,当您直接处理本机.NET对象时,[ComImport]接口类型等效不起作用。您需要隐藏人工COM代理背后的.NET对象才能使COM接口等效。

在我的问题的solution中,我最初使用ICustomQueryInterfaceMarshal.CreateAggregatedObject来聚合.NET对象,因此将其公开为COM对象。

后来,我最终实现了我自己的IUnknown运行时存根(使用Marshal.GetFunctionPointerForDelegate for AddRefReleaseQueryInterface),我用它作为pOuter(控制IUnknown)对象为CreateAggregatedObject,所以它没有违反COM身份规则。那是黑客,但它解决了我的问题。

另一答案

如果过滤器已在系统中注册并且您知道它的CLSID,那么您可以使用:

Type filterType = Type.GetTypeFromCLSID(filterClsid);
var filter = (IBaseFilter)Activator.CreateInstance(filterType);

如果过滤器未在系统中注册,但您知道dll-location和CLSID,则可以像在C ++中那样进行。你需要一些P / Invokes!打电话给LoadLibraryEx,然后拿到IClassFactory。有了这个你可以IClassFactory::CreateInstance你的过滤器。

我知道这很有效,因为我们已经完成了,我们只使用这种方法来处理自定义directshow过滤器。

以上是关于在C#中实例化托管COM对象的主要内容,如果未能解决你的问题,请参考以下文章

创建片段而不从 java 代码实例化它

如何通过应用程序委托使用托管对象上下文实例化还原的视图控制器?

由非托管 (C++) COM 服务器实例化的托管 (C#) 控件在 Windows 更新后中断

片段事务中的实例化错误

在片段中接收 NFC 的应用程序创建托管活动的新实例

我们可以在AppDelegate中实例化核心数据的单个对象并在整个应用程序中使用它吗?