Ich habe eine Anforderung, die ich denke, Ich habe eine Lösung für, aber ich würde gerne Eingang, falls ich etwas vermisse oder mich für Fehler auf der Straße einrichten.Spät Binding und WithEvents mit VBA
Die Anforderung
implementieren einige neue Business-Logik in einer neuen Bibliothek (unter Verwendung von C#), die ihren Status durch Ereignisse zurückmeldet. Die Bibliothek wird von einer vorhandenen VBA-Lösung aufgerufen (kann dies noch nicht ändern). Die Bibliothek ist VBA über COM Interop ausgesetzt - hier keine Probleme.
Zusätzlich zur "Basis" -Funktionalität, die diese neue Bibliothek bietet, muss die Basisfunktionalität durch "benutzerdefinierte" Funktionalität ersetzt werden.
Sowohl die Basis- als auch die benutzerdefinierte Funktionalität implementieren die gleiche Schnittstelle, aber die internen privaten Methoden jeder Methode unterscheiden sich aus verschiedenen Gründen.
In VBA
Ich brauche entweder die Basisbibliothek oder benutzerdefinierte Bibliothek (und vielleicht auch andere kundenspezifische Bibliotheken, die die gleiche Schnittstelle in Zukunft implementieren) aufrufen zu können. Ohne die Anforderung, auf die Bibliotheken zu antworten und sie anzuzeigen, könnte ich Late Binding verwenden, um das Objekt zur Laufzeit zu instanziieren. Da ich jedoch auf die Ereignisse reagieren muss, die von den Bibliotheken ausgelöst werden, muss das Schlüsselwort WithEvents
verwendet werden, wenn die Variable in VBA deklariert wird.
Wenn ich nur die Basis-Bibliothek unterstützen ich etwas wie das folgende tun könnte:
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
Da ich auf benutzerdefinierte Implementierungen dieser Bibliothek unterstützen (von denen ich einige über jetzt wissen, andere die ich noch nicht kenne) Ich würde wie spät binden, um dieses Szenario zu behandeln.
WithEvents kann jedoch nicht mit Late Binding verwendet werden, obwohl ich möglicherweise auf einen Workaround gestoßen bin. In meinem Szenario werde ich immer einen Verweis auf die Basisimplementierung haben. Dies geschieht nur unter bestimmten konfigurierten Umständen, bei denen die Basisfunktionalität durch eine benutzerdefinierte Implementierung ersetzt wird.
Da die Basis und kundenspezifische Bibliothek (n) die gleiche Schnittstelle teilen, ich habe den folgenden Code in einem Proof of Concept arbeiten:
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
Diese Implementierung ohne Fehler funktioniert (sowohl bei der Kompilierung und Laufzeit), aber ich bin ein bisschen zögerlich, diese Lösung in Zukunft zu verwenden, weil ich nicht das Gefühl habe, dass ich ein solides Verständnis davon habe, wie das eigentlich funktioniert. Mein Verdacht ist, dass es funktioniert, weil sowohl die Basis- als auch die benutzerdefinierten Bibliotheken die gleiche Schnittstelle haben, also ist COM mit der späten Bindung über die Aussage "glücklich", aber ich habe Angst davor, was ich hier vermisse, das mich möglicherweise Kummer verursachen wird die Straße runter.
Meine Frage
Ist es „sicher“ auf diese Problemumgehung verlassen für späte WithEvents
Bindung verwenden, und wenn ja, warum?
Wenn nicht, gibt es Alternativen, die ich implementieren könnte (darüber hinaus nicht mit VBA, die ich in diesem Szenario keine Wahl habe)?
Ich werde nicht einmal vorgeben, die Antwort zu wissen, aber ich würde denken, dass solange beide Klassen die gleiche Schnittstelle verwenden, alles in Ordnung ist. Schließlich ist es bei der Verwendung von COM Interop erforderlich, eine Schnittstelle anstelle einer konkreten Implementierung zu verwenden. Soweit es VBA betrifft, sind sie vom gleichen Typ (im Wesentlichen). Wirklich interessante Frage übrigens. – RubberDuck