我们有一个用非托管 C++ 声明和实现的 COM 接口。我们不再希望保留这个程序集,但确实需要进行一些更改,并且仍然向后兼容。
我想做的是用 C# 编写所有新代码,并使其 ComVisible。从此线程中,我看到了对 TreatAs 的引用以替换旧界面。
对于 ProgId、Guid 等,我的想法与 Jonathan Peppers 的思路相同。我将实现与旧版本相同的接口,作为新实现的包装器。我还在考虑添加与生成的互操作包装器中完全相同的 MarshalAs 属性,以确保数据类型相同(如果可能)。
在处理这个问题时我还应该考虑什么吗?有谁有进行此转换的经验吗?
编辑:我确实有服务器的 IDL 文件。我不确定是否有办法可以基于此自动生成代码。 COM 不是我很熟悉的东西。
编辑问:我应该如何处理现有客户端使用的 HRESULT?
添加:我想我应该向其他读者指出不同的修复 ,这不适用于我的场景,因为我无法使用现有 com:
Bjørnar Sundsbø重新编译所有 .NET 应用程序
We have a COM interface declared and implemented in unmanaged C++. We no longer wish to maintain this assembly, but do need to make some changes, and still be backward compatible.
What I want to do, is to write all the new code in C#, and make it ComVisible. From this thread I see a reference to TreatAs to replace the old interface.
I was thinking along the same path as Jonathan Peppers regarding ProgId, Guid, etc. I will implement the exact interface as the old version as a wrapper to the new implementation. I am also thinking about adding MarshalAs attributes exactly as in the generated interop wrapper to be sure the data types will be the same, if possible.
Are there anything else I should consider while working with this? Anyone with experience doing this conversion?
EDIT: I do have the IDL file for the server. I am not sure if there is a way I can auto generate the code based on this. COM is not something I'm very familiar with.
EDIT Q: How should I deal with HRESULT used by existing clients?
ADDED: Figured I should point other readers to a different fix, which is not available for my scenario as I can't recompile all the .NET applications using the existing com:
Bjørnar Sundsbø
发布评论
评论(2)
一种快速入门方法:
这应该从一开始就使所有类型和方法签名正确。它是将现有 COM 接口移植到 C# 的一个很好的起点。
One quick way to get started:
This should get all your types and method signatures correct from the start. It is a great starting point for porting an existing COM interface to C#.
这似乎是设计的 防止从托管客户端使用托管 COM 对象。
以下是相同问题的一些链接,以及此帖子,提供了一些解决方案。另请查看 Jonathan Peppers 提供的答案,了解如果您只需要从非托管应用程序使用它,如何开始。
我认为解决这个问题的唯一方法是一个混乱的解决方案,我在 C# 中创建新代码,在其上添加一个 COM 层。然后创建一个额外的 COM 层作为非托管 C++,它访问第一层,以便我的 .NET 应用程序可以访问它。
{非托管COM暴露原始接口} => {重写COM的原始逻辑的托管COM}。然后,所有现有应用程序都将访问“{非托管 COM...}”。如果我足够绝望,这可能是一个办法。目前我正在放弃这种方法并寻找其他解决方案。
如果可以,请重新编译托管应用程序以使用新程序集。您仍然可以使用 VB6、非托管 C++ 等中的托管 COM。如果您仍然需要从托管引用为 COM,您也许可以使用 引用的帖子之一,只要您不需要创建互操作包装器即可。
It seems to be by design to prevent managed COM object from being used from a managed client.
Here are some links to the same problem, as well as this thread, providing some solutions. Also take a look at the answer Jonathan Peppers provided to see how to start out if you only need to use it from unmanaged applications.
The only way I figure I could work around this, is a messy solution where I create the new code in C#, add a COM layer on top of that. Then create an additional COM layer as unmanaged C++ which accesses the first layer so, that my .NET applications can access it.
{Unmanaged COM exposing the original interface} => {Managed COM with rewrite of the original logic of the COM}. All existing applications will then access the "{Unmanaged COM...}". If I get desperate enough, that might be a way. For now I'm abandoning this approach and looking for other solutions.
If you can, recompile your managed application to use the new assembly, do so. You can still use that managed COM from VB6, unmanaged C++, etc. If you still need to reference as a COM from managed, you might be able to create new instances using the approach specified in one of the referenced posts, as long as you don't need to create an interop wrapper.