通过COM创建TimeSpan实例

时间:2014-04-15 08:31:03

标签: vba excel-vba com com-interop timespan

我正在使用从VBA向COM公开的.NET库。库接口使用TimeSpan类作为可设置属性。有什么方法可以通过COM构造TimeSpan,以便我可以为属性赋值吗?

如果我为COM注册程序集,我发现我可以实例化一些System程序集类型:
https://docs.microsoft.com/en-us/previous-versions/ms364069(v=vs.80)#calling-into-the-framework

但它似乎根本没用,因为TimeSpan是一个不可变对象,其值只能通过带参数或静态工厂方法的构造函数来设置。这些都不能通过COM调用,afaik。

我希望有一些技巧。例如,可以使用理论上可以转换为COM的以下C#代码间接创建TimeSpanDateTime类是否暴露给COM(它不是什么,与TimeSpan相反):

new DateTime().AddMilliseconds(1000).TimeOfDay;

显然,我可以用一些工厂方法实现我自己的.NET程序集暴露给COM。但是我希望只使用“标准”.NET库或普通VBA代码来解决这个问题。

1 个答案:

答案 0 :(得分:3)

许多基本.NET类型都具有[ComVisible(true)]属性,因此可以在COM互操作中使用它们。 TimeSpan也是如此,CLR会自动为你编组。

麻烦的是,没有明确表示时间跨度的标准COM自动化类型。就像DateTime一样,它被编组为缩放的 double ,0表示12/30/1899,并且每天增加1.0。 TimeOfDay是分数。 DateTime.ToOADate()返回它。在一段时间内没有采用这样的标准。与VBScript DateDiff()函数相比,它返回​​一个整数,其值取决于您要求的单位。

因此,CLR几乎没有办法让每个人都满意,它会对TimeSpan.Ticks属性值进行填充和整理。 64位整数,单位为100纳秒。相应的自动化类型为VT_I8。

麻烦的是,许多COM主机在32位整数处逐渐消失。 VBA确实如此。所以它们往往会摔倒,常见的错误信息是“不支持自动化类型”。

您无法解决任何问题,您可以使用VBA 支持支持的其他类型公开该值。例如 double 。您只需要记录COM客户端应该如何解释它。值0完全是明确的,只有缩放是设计选择。由于TimeSpan已经有一个属性,它将时间跨度作为 double 返回,因此您可能更喜欢毫秒。因此,您只需返回TimeSpan.TotalMilliseconds并使用TimeSpan.FromMilliseconds()返回往返。像DateTime一样,使用一天的单位也很有吸引力。使用TimeSpan.TotalDays和TimeSpan.FromDays()。将其公开为 int 也是一种选择。但要注意溢出,如果你选择msec,那么超过27天的时间跨度就无法表示。由您决定。