【发布时间】:2016-07-29 12:23:58
【问题描述】:
我正在尝试使用 C# 中的 COM 接口,该接口公开 tlbimp 生成的以下接口:
[Guid("7DDCEDF4-3B78-460E-BB34-C7496FD3CD56")]
[TypeLibType(TypeLibTypeFlags.FDual | TypeLibTypeFlags.FNonExtensible | TypeLibTypeFlags.FDispatchable)]
public interface IFred
{
[DispId(1)]
IBarney Pall { get; set; }
}
[Guid("E390230E-EE9C-4819-BC19-08DAB808AEA9")]
[TypeLibType(TypeLibTypeFlags.FDual | TypeLibTypeFlags.FNonExtensible | TypeLibTypeFlags.FDispatchable)]
public interface IBarney
{
[DispId(1)]
double Wilma { get; set; }
}
生成的包装程序集不包含IBarney 接口的实现。我创建了一个实现IBarney 接口的C# 结构,如下所示:
[Guid("2C61BA37-7047-43DB-84B1-83B4268CF77B")]
[ComVisible(true)]
public struct Barney : IBarney
{
public double Wilma { get; set; }
}
哪个“有效”,现在的问题是,Barney 实例是按值编组还是按引用编组?由于涉及到网络开销,这一点很重要。理想情况下执行如下操作:
fredInstance.Pall = new Barney { Wilma = 0.37 };
将导致单次网络往返。我如何验证这一点,或者如何告诉 COM 互操作我的 Barney 结构应该始终按值编组?
更新:
鉴于 Hans Passant 的评论。设计这个的“正确”方法是什么?允许一个简单结构用作 COM 接口的“属性”值所需的 IDL 是什么?查看生成接口的 IDL,我目前正在使用添加一个带有默认 IBarney 接口的 coclass 声明就足够了,对吧?
【问题讨论】:
-
无需检查,COM 从不关心对象是如何实现的,只对接口指针起作用。这将是每个属性访问的往返。从技术上讲,这可以通过自定义代理/存根来解决,但这对于 .NET 来说是遥不可及的。考虑实施 IPersistStream。
-
@HansPassant:我猜你的意思是在 COM/native 端实现 IPersistStream?由于谷歌搜索它只会显示对非 .NET 内容的引用。
-
您是否在两端都使用 C# 工作?或者是否涉及任何其他语言?即:你为什么首先创建COM接口?为什么你使用idl来定义你的接口?您需要自动化兼容接口吗?你知道“纯”COM 和 COM+自动化之间的区别吗?
-
我在一家同时使用 .NET 和 C++ 的公司工作,两个世界之间的互操作是使用 COM 完成的。我个人参与了 .NET 开发。要更改 IDL/COM 部分,必须进行一些协商,但原则上可以更改。 COM 接口的原始要求之一是它们与 OLE 自动化兼容。我(正如您可能猜到的)对 COM 不了解,我不知道 COM 和 COM+ 自动化之间的区别。感谢任何指向资源的指针。
-
好的,所以你需要 C++ 和自动化(我说的不是 COM+,而是 COM+ 自动化 :-)。在这种情况下,您必须知道自动化将大大减少您可以使用的类型(它也有其优点):msdn.microsoft.com/en-us/library/cc237562.aspx(请注意,并非所有客户端都支持 VT_RECORD,这是一个较晚的添加)。最简单的是使用 SAFEARRAY(UI1 的)或 VARIANT(可以包装任何自动化类型)。 PS:当您想发表评论时,不要忘记添加@
。我刚刚路过,发现你回复了我
标签: c# com marshalling com-interop