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

问题描述 投票:0回答:2

我编写了几个纯.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过滤器一起使用 - 这甚至可能吗?

c# .net com directshow
2个回答
3
投票

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

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

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


2
投票

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

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.