Late Binding and WithEvents Using VBA

I have a requirement that I decide that I have a solution, but I would be grateful for the input in case I missed something or am looking forward to failure in the future.

Demand

Introduce new business logic in a new library (using C #) that reports its status through events. The library will be called from an existing VBA solution (cannot change this). The library is exposed to VBA through COM Interop - no problem here.

In addition to the “core” functionality opened by this new library, I need to allow the replacement of the base functionality with “user-defined” functions along the way.

Both the basic and user functionalities will implement the same interface, but the private private methods of each will be different for various reasons.

In vba

I need to be able to reference either the base library or a special library (and possibly other user libraries that will implement the same interface in the future). If it weren’t for the requirement to respond and display messages from libraries, I could just use Late Binding to instantiate the object at runtime. However, since I need to respond to events that occur in libraries, I need to use the WithEvents keyword when declaring a variable in VBA.

If I only needed to maintain the base library, I could do something like the following:

 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 

Since I have to support custom implementations of this library (some of which I know now, others that I do not know about yet), I would like to use late binding to handle this script.

However, WithEvents cannot be used with Late Binding, although I may have come across a workaround.

In my scenario, I will always have a reference to the base implementation. This will only be in certain, customized circumstances, when the basic functionality will be replaced by a user implementation.

Since the base and user libraries (s) have the same interface, I have the following code working in proving the concept:

 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 

This implementation works without errors (both at compile time and at runtime), but I am a little hesitant about using this solution in the future because I don’t feel like I have a clear understanding of how \ why this really works. My suspicion is that it works because both the base and user libraries use the same interface, so COM is “happy” with late binding via the CreateObject statement, but I'm afraid it might be missing here, which could potentially result to I mourn along the road.

My question

Is it “safe” to rely on this late binding solution with WithEvents , and if so, why?

If not, are there any alternatives that I could implement (other than using VBA, in which I have no choice in this scenario)?

+6
source share
2 answers

Private WithEvents Processor...

The WithEvents statement instructs to detect value events and associate them with available code handlers. When you initialize the Processor value, you will have the following actions that occur behind the scene: checking the COM server class information, identifying the available event interface, detecting the connection point container, connecting to the events of the found interface, providing a callback to receive calls.

When / if all of the above happens and succeeds, the events fired from the COM server reach your handlers. On the VB.NET code side, there are no additional assumptions as to who exactly implements the events, so you can switch servers on the go if they are valid COM servers with connection points and class / type information.

+2
source

As far as I understand how this works, you are right in your assumptions. As long as the "custom" engine provides all the events and properties of the engine that are accessed (called) by VBA code accessing the engine, you will have no problems. I have not tried this, but I am sure that you can hedge by building in the standard class some common events and properties (only in the name) that you could actively use later with one of the user formulations.

+1
source

Source: https://habr.com/ru/post/979952/


All Articles