CreateInstance () - Sto facendo questo diritto?
-
09-09-2019 - |
Domanda
Sto cercando di mettere insieme un sistema di plugin con .NET, e non sono sicuro se sto facendo in modo corretto. La base del sistema è che una directory specifica ({AppPath} / plugins /) avrà un sacco di DLL precompilati, e voglio guardare attraverso ognuna con la riflessione, e per ogni classe a disposizione, se si eredita una classe base specifica (questo è definito in un altro DLL, ma andrò in quella successiva), quindi creare un'istanza di esso e chiamare una funzione specifica in tale istanza.
Public Sub ScanPluginsInDirectory(ByVal Directory As String)
Dim Plugins As New IO.DirectoryInfo(Directory)
Dim Files As IO.FileInfo() = Plugins.GetFiles("*.dll")
Dim CryptType As Type = GetType(CryptPluginBase)
Dim PluginsData as List(Of LoadedPluginsInfo)
For Each DllFile As IO.FileInfo In Files
Try
Dim thisAsm As Assembly = Assembly.LoadFrom(DllFile.FullName)
Dim ClassDefs = thisAsm.GetTypes().Where(Function(type) CryptType.IsAssignableFrom(type))
For Each ClassDef As Type In ClassDefs
Dim A As Object
A = ClassDef.Assembly.CreateInstance(ClassDef.Name)
PluginsData.Add(New LoadedPluginsInfo(A.Plugin(), False))
Next
Catch ex As Exception
Continue For
End Try
Next
End Sub
Il problema specifico che ho è, io non sono sicuro che questo è il modo giusto per farlo. Sarebbe il metodo che sto cercando di fare il lavoro, se si può supporre che A.Plugin()
esiste realmente ed eventuali strutture e classi si fa riferimento qui sono esenti da bug? Se qualcuno avrebbe bisogno di più il codice al fine di aiutare, posso postarlo.
Soluzione
Nel complesso la strategia dovrebbe funzionare. La chiamata Assembly.LoadFrom caricherà il gruppo bersaglio nel processo. Da lì è possibile fare l'ispezione tipo e creare istanze di quei tipi.
Penso che il modo più semplice e affidabile per creare l'istanza è quello di utilizzare il metodo Activator.CreateInstance.
For Each def As Type in ClassDefs
Dim inst = Activator.CreateInstance(def)
PluginsData.Add(new LoadedPluginsInfo(inst.Plugin(), False))
Next
A seconda degli obiettivi, un altro suggerimento sarebbe quello di spostare il blocco try / catch nel circuito, invece di fuori di esso. Avendo il blocco try / catch all'esterno del ciclo significa che se un dato tipo in un assembly non ha un errore, si scarta tutti i tipi da tale assemblaggio. Muoversi dentro vi permetterà di scartare solo i tipi che non funzionano come expect.d Il comportamento attuale potrebbe essere il vostro intento però.
Altri suggerimenti
Questo dovrebbe funzionare, ho usato questo genere di cose in alcuni progetti prima. Ho guardato specificamente per un costruttore e invocato, ma a parte che era la stessa idea.
Ma si potrebbe desiderare di guardare MEF , che si prende cura di un sacco di cose per voi per una architettura a plugin (se siete disposti ad aspettare un po 'per la versione finale, è ancora CTP per ora).