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

时间:2014-06-02 12:19:17

标签: c# .net com directshow

我已经编写了几个纯.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过滤器一起使用 - 这是否可能?

2 个答案:

答案 0 :(得分:3)

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

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

后来,我最终实现了我自己的IUnknown运行时存根(使用Marshal.GetFunctionPointerForDelegate AddRefReleaseQueryInterface),我将其用作{ {1}} pOuter的{​​IUnknown}对象,因此它没有违反COM身份规则。那是黑客,但它解决了我的问题。

答案 1 :(得分:2)

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

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

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

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