就像主题说的那样,我写了一个C#类,比如Test,然后把它编译为DLL并将它作为COM自动化服务器公开给Excel.现在,您可以直接或通过VBA函数在Excel公式中调用该类的方法,VBA函数本身在引擎盖下调用它们.在第二种情况下发生的事情是相对透明的(你写了代码!),而在第一种情况下,我假设一个Test实例被透明地实例化然后使用(它必须由于暴露的方法不是 - 并且 - 从我读过的内容 - 不能是静态的)但究竟何时以及如何不清楚.因此,我的问题是:在此设置中调用的自动化服务器的精确生命周期是什么?
一个辅助问题是,是否有办法在公式中进行直接调用,而通过VBA调用是否使用单个单独的Test实例?我想我已经知道如何让所有VBA程序使用单个Test实例,但即便这样,只要在公式中直接调用Test方法,就会创建第二个.
最后,如果Test类在类级别(即静态资源)保存资源,那么何时以及如何处理它们?同样,这引出了.Net/COM Interop何时创建和销毁Test类的问题.
精度:服务是DLL,而不是应用程序,Excel应该是唯一使用它的程序,尽管可能会打开多个电子表格副本.这是Excel 2007.
“Excel 应该是唯一使用它的东西”:
我发现,实现此应用程序限制的唯一方法可能是黑客或神秘的。AFAIK:保留您的库引用的调用应用程序白/黑名单的硬编码或外部列表,并在每个库加载时执行查找。从本质上讲,COM 类暴露于整个世界……字面意义上的。
“是否有办法既可以在公式中直接调用,又可以通过 VBA 调用 Test 的单个实例?”
您必须将其视为单例,要么非常努力地仅持续使用一个实例,要么创建一个“单例包装器”函数来保存一个静态变量,该变量在 VBA 代码中保存对象引用。
“如果该测试类拥有类级别的资源(即静态资源),那么您应该何时以及如何处置它们? ”:
它们(通常)在应用程序终止时自动清除,或者当应用程序调用 COM对象的“finalize”方法时(如果适用于 COM 类库的内部工作),或者当对象的引用计数降至 0 时(如果适用于 COM 类库的内部工作)。
我认为一个可能提供更好见解的问题是:“我正在使用的特定 COM 类如何处理自己的生命周期?” 有时,COM 对象是永久的,甚至在调用应用程序中的过程结束后仍然存在。根据 COM 类设计,可以使对象保持活动状态,无论调用应用程序中是否存在任何剩余的引用对象。有时,您需要显式销毁对象引用(使用 VBA“删除”方法),否则只要调用应用程序存在,该对象就可以持续存在(这可能是该特定 COM 类的设计者的意图)。从一个网站到另一个网站的 ActiveX 对象的持久性就可以明显地看出这一点,这也是浏览网络时最好“不信任任何人”的主要原因之一。更糟糕的是,如果永久对象本身在内部引用其他对象和资源。
要真正掌握类的生命周期,您必须研究 COM 类作者提供的文档。在这种情况下,您需要从 COM 类库中设计一种方法来强制执行或提供外部可访问的方法来强制执行生命周期标准(实现 IDisposable、提供您自己的公共Dispose()方法等)。
DLL 的引用链接肯定会在调用应用程序的整个生命周期内保持活动状态,甚至在您尝试创建第一个对象时就诞生了。AFAIK,你对此无能为力。仅通过使用某些第 3 方系统信息应用程序监视 DLL 应用程序所有权信息即可明显看出这一点。这是有道理的,因为它可以节省每次需要时加载和卸载 DLL 的资源。