Peculiar architecture interfaceing .NET to out-of-process di AutoCAD

5

Ho scritto una serie di classi per interagire con AutoCAD da un assembly .NET out-of-process, ma sembra che la mia architettura di classe e le sue interazioni siano insolite. Sto lottando per trovare un modo migliore per progettarli.

Alcuni background:

Sto leggendo i dati di diverse migliaia di disegni di AutoCAD, raccogliendo dati da distinte materiali, cartigli e altre entità. AutoCAD può essere interfacciato con un altro processo in diversi modi. Un modo è utilizzare la libreria di tipi COM di AutoCAD che esegue il marshalling di ogni chiamata ed è relativamente lento (circa 6 secondi per disegno). Un modo molto più veloce è caricare una DLL .NET nel processo di AutoCAD ed eseguire il codice lì. Questo componente .NET espone un'interfaccia COM (chiamiamola IAutoCADDataReader) che puoi chiamare dal mondo esterno. Se si chiama un metodo su questa interfaccia, è possibile raccogliere i dati e restituire un oggetto che contiene tutti i dati raccolti (chiamarlo IDomainObject). Funziona bene e impiega circa 200 ms (enorme miglioramento) poiché l'interazione con il database di AutoCAD era tutto in-process e alla fine si eseguiva il marshalling di un solo oggetto complicato.

La parte sopra del disegno di cui sono felice. Quello che mi infastidisce è quello che faccio con IDomainObject quando ritorna nel mio assembly .NET principale. Ovviamente è un _COMObject che posso trasmettere a un IDomainObject, ma in realtà non esiste nel mio assembly gestito, è uno stub o un proxy. Quando leggo i suoi dati, chiama attraverso il confine del processo. Se AutoCAD viene spento, riceverò un errore RPC. Mi piacerebbe davvero che questo oggetto esistesse indipendentemente dalla sua fonte originale. La soluzione naturale è clonarla e scartare l'oggetto COM.

Ora, di solito un metodo Clone si trova sull'oggetto stesso. Questo si adatta con SRP dato che chi vorrebbe saperne di più sulla clonazione di quanto sarebbe? Questa non è una soluzione in questo caso poiché un metodo Clone su questa interfaccia IDomainObject verrebbe effettivamente eseguito nel processo di AutoCAD e mi avrebbe dato un altro oggetto COM. Quindi, ignorando SRP, ho scritto una funzione Clone privata nell'assembly gestito che scorre su vari array e altri dati in IDomainObject e restituisce un DomainObject completamente gestito (non un'interfaccia). Questo nuovo oggetto può ora esistere indipendentemente da AutoCAD, può fare tutto ciò che voglio nel mondo gestito e non sarà soggetto a errori RPC.

Mi piace il risultato finale di questo processo complicato da quando ho finito con quello che volevo in modo abbastanza veloce, ma non posso fare a meno di pensare che questo è un modo strano di progettare una cosa del genere. Qualcuno di voi ha qualche suggerimento su come questo disegno può essere rifattorizzato per renderlo meno particolare?

Un'altra critica che potrebbe essere livellata in questo tipo di clonazione è che fallisce il principio Aperto / Chiuso. Se estendo uno qualsiasi dei sottotipi all'interno di IDomainObject, l'operazione clone non sarà più corretta. Dovrei aggiornare questa funzione clone privata in quel momento. Questo mostra davvero come funziona questa soluzione per ora, ma viola diversi principi che probabilmente mi morderanno mentre questo progetto continua ad evolversi. Come sviluppatore di software in-company, questa roba verrà utilizzata ed evoluta per anni e non sarebbe bello avere queste cattive pratiche all'inizio.

    
posta Mike 25.03.2015 - 18:09
fonte

1 risposta

3

Un metodo relativamente semplice e generico per passare oggetti .NET oltre i limiti del processo consiste nell'utilizzare la serializzazione. Assicurati che il tuo DomainObject sia serializzabile, quindi puoi implementare il tuo metodo Clone serializzando il tuo oggetto su un flusso di memoria e deserializzalo da lì all'interno del tuo componente principale fuori processo.

L'abbiamo usato insieme ai file mappati in memoria come una forma di IPC per passare una gerarchia di oggetti complessi, ma sono abbastanza sicuro che funzionerà anche nella tua situazione senza questi dettagli tecnici aggiuntivi (e in caso contrario: converti la memoria flusso a una stringa, quindi è possibile applicare la meccanica COM per il passaggio di stringhe tra i processi). Questo risolve esattamente i problemi che hai descritto sopra: non hai bisogno di scrivere alcun codice per iterare sugli array interni (la serializzazione .NET "magic" lo farà per te), e quando estendi i tuoi sottotipi, non c'è nulla da cambiare in il tuo metodo clone.

    
risposta data 25.03.2015 - 19:38
fonte

Leggi altre domande sui tag