使用C#创建COM扩展 - 值得吗?

时间:2009-06-17 20:28:28

标签: c# com interop

我正在处理以下问题:(第三方)软件(Software A 我们广泛使用允许使用组件对象模型(COM)接口(实际上是几个接口)编程它所谓的“扩展”。它提供了这些接口的MIDL文件以及作为SDK的一部分的Visual C ++的“项目模板”(IDL文件,标题和接口已经存在,只缺少接口函数的实现)。为了可以兼容,所有扩展都必须符合(即必须实现)给定的COM接口结构。

然而,由于我对C ++的熟悉程度相当有限,我希望在C#和.NET中实现COM - 另一方面,预定义的接口大量使用指针和自定义数据结构,所以我是想知道我是不是更好地在他们的原生C ++中实现接口,而不是试图用C#重新创建所有东西。

可能还有一点背景:最终的目标是从软件A内部控制一块自定义硬件(通过USB)。我已经使用DLLimport编写了一个包装驱动程序(另一个第三方软件)的小型.NET应用程序,这令人惊讶地无痛。换句话说,我试图构建的COM对象本质上是(第三方)软件A和(第三方)设备驱动程序B之间的桥梁,它必须符合A给出的接口规范。


示例MIDL代码:

[id(0x00000004)]
  HRESULT GetWaveData([in] BSTR name,[out] IWaveData ** data);
  [id(0x00000005)]
  HRESULT GetImageData([in] BSTR名称,[out] IImageData **数据,[out] Palette * Palette);
  [id(0x00000006)]
  HRESULT SetVariable([in] BSTR name,[in] IVariableData * variable);

4 个答案:

答案 0 :(得分:5)

如果不完全了解问题,就不可能回答这个问题。但一般来说,我会选择C ++路线。通过向世界添加CLR,您将不得不处理互操作问题,并可能在C#中处理讨厌的指针问题(因为它的性质是处理低级硬件相关的东西)。因此,您的真正选择可能是不洁净的C#源或使用C ++。我想我会选择后者。

答案 1 :(得分:2)

从技术上讲,你不是用C ++而是用MIDL实现接口。 它是一种单独的界面语言,值得知道你是否要做COM工作。

无论如何,使用.NET interops实现COM对象并不罕见,但这两者并不是真正兼容的技术。除非你写的是非常简单的对象,否则你会遇到陷阱。

为了帮助您入门,这里有一些随机的指针以及我过去使用过的几篇文章。

  • COM是一种界面驱动技术。一遍又一遍地重复这个。
  • 使用MIDL单独开发接口定义。
  • COM垃圾收集是确定性的(引用计数),但是当与.NET一起使用时会开始崩溃,垃圾收集会自动且不可预测地发生。
  • 处理Eventsinks /事件处理程序很难看。

您会遇到的一小部分头痛: http://www.codeproject.com/KB/cs/LingeringCOMObjects.aspx

更多关于为什么不让Visual Studio为您自动生成COM接口的原因: http://blogs.msdn.com/mbend/archive/2007/04/17/classinterfacetype-none-is-my-recommended-option-over-autodispatch-autodual.aspx

过渡事件: http://www.west-wind.com/presentations/dotnetfromVfp/DotNetFromVfp_EventHandling.asp

答案 2 :(得分:1)

如果它为您提供了优势,那么您应该只为此目的使用.NET。例如,我们曾经需要webservices invokation,并且在.NET中对它的支持要好得多,所以我们采用了这种方式。在您的情况下,优势在于您更熟悉.NET并且可能值得选择。

但是,如果在.NET中实现COM对象,则必须要求.NET运行时使用必须使用该对象的每台机器。此外,您可能在实现难以编组的自定义类型的接口时遇到问题。

您需要比较优势 - 在您的情况下更熟悉 - 与您遇到的技术负担 - 可能的部署和编组问题。

我个人认为只有在需要功能的情况下才能选择.NET路径(如webservices invokation)。

答案 3 :(得分:1)

听起来您正在做的决定是使用本机应用程序还是基于.NET的应用程序。

您需要考虑以下事项:

  1. 部署问题:您要在哪里部署此应用?它会在数百个工作站或仅仅几个工作站上运行吗?您将对安装它的机器进行多少控制?请记住,您必须确保安装了正确版本的.NET平台;

  2. 维护问题:您显然更熟悉.NET,但是谁会长期关注应用程序?他们会被期望熟悉C ++吗?由于“管家”是其中非常重要的一部分,因此本土开发确实是与管理开发不同的鱼类;

  3. 第三方依赖:听起来像是您尝试使用第三方COM库通过USB与您的设备进行通信。但是,你已经提到你已经为硬件驱动程序编写了一个.NET包装器 - 你能详细说明一下,因为这有点令人困惑。如果可能,如果没有太多麻烦,不要引入依赖;

  4. 资源限制:如果您的应用程序将“在野外”安装,那么硬件的约束是什么?使用非托管环境进行编程允许您对应用程序将使用多少内存以及CPU密集程度进行细粒度控制 - 当然,这是对托管层负责管理资源管理的权衡

  5. 通常,如果您正在开发一个不需要使用不同硬件配置部署到数千个用户的应用程序,我会选择.NET平台。 .NET上的COM互操作相对轻松,在托管平台上进行编程意味着您可以专注于重要的事情。如果你以前从未在非托管环境中进行编程(C / C ++),那你就有点震惊。