Da qualunque programma .NET, puoi
importare assembly esterni (ad esempio, una
Class Library sottoforma di DLL) usando funzionalità specifiche come le classi di
System.Reflection, ad esempio .
Questo presuppone ovviamente che nella libreria specificata sia stato scritto e compilato il codice che implementa il tipo con la logica di importazione a cui fare riferimento. Ciò garantisce la libertà di sostituire questa libreria in modo separato dall'eseguibile, anche se è sempre necessario passare da una fase di "build" per poterla creare.
Potremmo considerare questo approccio come un
esempio di plug-in per l'applicazione.
Per
eseguire codice dinamicamente invece, occorre coinvolgere (appunto) la
programmazione dinamica in .NET, ovvero quelle classi che sono in grado di compilare codice "al volo", magari contenuto in un file sorgente o in una risorsa che può essere modificata, generando in memoria nel runtime i tipi corrispondenti, che possono successivamente essere utilizzati come qualsiasi altro oggetto, invocandone i metodi specifici.
Queste opportunità fanno uso del
DLR (
Dynamic Language Runtime), una parte del framework .NET appositamente progettata per forme di programmazione basate su "late binding", ovvero su oggetti (tendenzialmente di tipo
dynamic o implementati in specifiche librerie) che rappresentano oggetti e metodi da invocare che il compilatore ignora in fase di build e, solo a runtime appunto, vengono "collegati" a oggetti veri e propri il cui codice dipende dalla fonte da cui hanno origine i tipi corrispondenti, codificati usando le classi indicate sopra, oppure usando uno dei tanti runtime esistenti che supportano linguaggi di scripting, ad esempio
IronPython.
Il concetto in breve è che vengono creati oggetti e invocati metodi scritti in C# o in linguaggi diversi, senza che il compilatore metta becco, e solo a runtime questi tipi vengono creati esattamente come ci si aspetta, compilando al volo codice C# contenuto in file di testo o altra risorsa, o usando una libreria come quella di
IronPython che svolge la stessa funzione ma interagendo con altri "motori" e linguaggi differenti.
Fai una ricerca usando le parole chiave indicate sopra e troverai numerosi esempi di come realizzare questa tipologia di architetture in modo semplice.
Se invece la struttura deve farsi più complessa, ad esempio emerge la necessità di definire uno o più "importatori", consentire una loro presentazione e scelta di quale utilizzare, andare a ricercarli all'interno di un folder, in breve se nascono altre esigenze di contorno, meglio allora dotarsi di librerie appositamente progettate per
architetture strutturate a plugin vere e proprie, che danno qualche servizio in più.
Ciao!