2014-12-19 11 views
6

Ho un requisito che I penso Ho una soluzione per, ma apprezzerei l'input nel caso mi manchi qualcosa o mi metto su per fallimento lungo la strada.Late Binding e WithEvents utilizzando VBA

Il requisito

implementare alcune nuove logiche di business in una nuova libreria (utilizzando C#) che riporta indietro il suo stato attraverso gli eventi. La libreria sarà invocata da una soluzione VBA esistente (non può ancora cambiarlo). La libreria è esposta a VBA tramite COM Interop - nessun problema qui.

Oltre alla funzionalità "di base" esposta da questa nuova libreria, è necessario consentire che la funzionalità di base venga sostituita dalla funzionalità "personalizzata" lungo la strada.

Entrambe le funzionalità di base e personalizzata implementeranno la stessa interfaccia, ma i metodi privati ​​interni di ciascuno saranno diversi per una serie di motivi.

In VBA

ho bisogno di essere in grado di richiamare sia la libreria di base o libreria personalizzata (e forse altre librerie personalizzate che implementano la stessa interfaccia in futuro). Se non fosse per il requisito di rispondere e visualizzare i messaggi dalle librerie, potrei semplicemente usare Late Binding per creare un'istanza dell'oggetto in fase di runtime. Tuttavia, poiché devo rispondere agli eventi generati dalle librerie, è necessario utilizzare la parola chiave WithEvents quando si dichiara la variabile in VBA.

Se solo avessi per sostenere la libreria di base avrei potuto fare qualcosa di simile al seguente:

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 

Dal momento che ho per supportare implementazioni personalizzate di questa libreria (alcuni dei quali conosco circa ora, gli altri che non conosco ancora) Vorrei come utilizzare l'associazione tardiva per gestire questo scenario.

Tuttavia, WithEvents non può essere utilizzato con Late Binding, sebbene possa essersi imbattuto in una soluzione alternativa.

Nel mio scenario, ho sempre avere un riferimento all'implementazione di base. Sarà solo in circostanze specifiche e configurate in cui la funzionalità di base verrà sostituita da un'implementazione personalizzata.

Dal momento che la libreria di base e personalizzati (i) condividono la stessa interfaccia, ho il seguente codice di lavoro in una prova di concetto:

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 

Questa implementazione funziona senza errori (sia in fase di compilazione e di esecuzione), ma sono un po 'titubante nell'usare questa soluzione in futuro perché non mi sento di avere una solida comprensione di come \ perché questo funzioni effettivamente. Il mio sospetto è che funzioni perché entrambe le librerie di base e personalizzate condividono la stessa interfaccia, quindi COM è "felice" con l'associazione tardiva tramite la dichiarazione CreateObject, ma ho paura di ciò che potrei mancare qui che potenzialmente mi causerebbe dolore lungo la strada.

La mia domanda

E ' "sicuro" a fare affidamento su questa soluzione alternativa per l'associazione tardiva utilizzando WithEvents, e se sì, perché?

In caso contrario, ci sono delle alternative che potrei cercare di implementare (oltre a non utilizzare VBA, che non ho una scelta in questo scenario)?

+0

Non ho intenzione di fingere di conoscere la risposta, ma penserei che fintanto che entrambe le classi utilizzano la stessa interfaccia, tu stai bene. Dopo tutto, è necessario utilizzare un'interfaccia anziché un'implementazione concreta quando si utilizza COM Interop. Per quanto riguarda VBA, sono dello stesso tipo (essenzialmente). A proposito, domanda davvero interessante. – RubberDuck

risposta

2

Private WithEvents Processor...

Il WithEvents dichiarazione istruisce per scoprire gli eventi di valore e collegarli ai gestori di codice disponibili. Quando si inizializza il valore Processor, si avranno le seguenti azioni che si svolgono dietro la scena: controllo delle informazioni sulla classe del server COM, identificazione dell'interfaccia degli eventi disponibile, rilevamento del contenitore del punto di connessione, connessione agli eventi dell'interfaccia trovata, chiamata di ritorno per ricevere l'evento chiamate.

Quando/se tutto citato accade e succede, gli eventi attivati ​​dal server COM raggiungono i gestori. Sul lato del codice VB.NET non ci sono ulteriori presupposti per chi implementa esattamente gli eventi, quindi è possibile cambiare server in movimento purché siano server COM validi con punti di connessione e informazioni sulla classe/tipo.

1

Per quanto ho capito come funziona, hai ragione a tua opinione. Finché un motore "personalizzato" espone tutti gli eventi e le proprietà del motore a cui si accede (chiamato) dal codice VBA che accede al motore, non si avranno problemi. Non ho provato questo, ma sono sicuro che puoi proteggerti inserendo nella classe standard alcuni eventi e proprietà generiche (solo di nome) che potresti utilizzare attivamente in seguito con una delle formulazioni personalizzate.