我有一个要求我想我有一个解决方案,但我会很感激输入,以防我错过了某些事情或让自己陷入困境。
要求
在新库(使用C#)中实现一些新的业务逻辑,通过事件报告其状态。该库将从现有的VBA解决方案中调用(但不能改变它)。该库通过COM Interop暴露给VBA - 这里没有问题。
除了" base"这个新库暴露的功能,我需要允许基本功能被" custom"未来的功能。
基本和自定义功能都将实现相同的接口,但由于各种原因,每个接口的内部私有方法都会有所不同。
在VBA中
我需要能够调用基本库或自定义库(以及将来实现相同接口的其他自定义库)。如果不需要响应和显示来自库的消息,我可以使用Late Binding在运行时实例化对象。但是,由于我需要响应库引发的事件,因此在VBA中声明变量时需要使用WithEvents
关键字。
如果我只需要支持基础库,我可以执行以下操作:
Private WithEvents Processor As MyDefault.RuleEngine
Public Sub Execute(StartDate As Date, EndDate As Date, SomeOtherParms As String)
Set Processor = New MyDefault.RuleEngine
Processor.Execute StartDate, EndDate, SomeOtherParms
End Sub
Private Sub Processor_OnProgressUpdate(ByVal percentComplete As Double)
'Show the progress on the UI to the user
End Sub
由于我必须支持这个库的自定义实现(其中一些我现在知道,其他一些我还不知道)我会喜欢使用后期绑定来处理这种情况。
但是,WithEvents不能与Late Binding一起使用,尽管我可能偶然发现了一种解决方法。
在我的场景中,我将始终引用基础实现。它只能在特定的配置环境下,其中基本功能将被自定义实现替换。
由于基本库和自定义库共享相同的接口,因此我将以下代码用于概念验证:
Private WithEvents Processor As MyDefault.RuleEngine
Public Sub Execute(StartDate As Date, EndDate As Date, SomeOtherParms As String)
If CustomConditionIsMet Then
'In real-life we'll look this info up from a table or config file
Set Processor = CreateObject("MyCustom.RuleEngine")
Else
Set Processor = New MyDefault.RuleEngine
End If
Processor.Execute StartDate, EndDate, SomeOtherParms
End Sub
Private Sub Processor_OnProgressUpdate(ByVal percentComplete As Double)
'Show the progress on the UI to the user
End Sub
这个实现没有错误(在编译和运行时都有效),但是我对使用这个解决方案有点犹豫,因为我不觉得我对如何实际工作的原因有了深刻的理解。我怀疑它是有效的,因为基本库和自定义库共享相同的接口,因此COM很快乐。通过CreateObject
声明进行后期绑定,但我害怕我可能会在这里失踪,这可能会让我感到悲伤。
我的问题
它是否安全"使用WithEvents
依赖此解决方法进行后期绑定,如果是,为什么?
如果没有,是否有任何我可以寻求实施的替代方案(除了不使用VBA,我不能在这种情况下选择)?
答案 0 :(得分:2)
Private WithEvents Processor...
WithEvents
语句指示发现值事件并将它们连接到可用的代码处理程序。初始化Processor
值时,您将在场景后面执行以下操作:检查COM服务器类信息,识别可用的事件接口,发现连接点容器,连接到找到的接口的事件,提供呼叫回来接收事件电话。
如果/如果所有提到的都发生并成功,则从COM服务器触发的事件将到达您的处理程序。在VB.NET代码方面,没有关于谁准确实现事件的额外假设,因此可以随时切换服务器,只要它们是具有连接点和类/类型信息的有效COM服务器。
答案 1 :(得分:1)
据我了解它是如何工作的,你的猜测是正确的。只要"定制"引擎公开了访问引擎的VBA代码访问(调用)的所有事件和引擎的属性,你将没有问题。我没有尝试过这个,但我相信你可以通过在标准类中构建一些通用事件和属性(仅限名称)来对冲,以后可以使用其中一种自定义公式积极地利用它。