Mi sono ritrovato a dover sviluppare del codice che in base all'opportuna configurazione presente in un DB (ma potrebbe essere anche un .config...) imposta le proprietà di un dato oggetto.
La Reflection (System.Reflection) è la soluzione, e a parte la non sempre ampia documentazione, è pure una soluzione semplice.
L'esempio che ho sviluppato prevede l'esistenza di una tabella di struttura simile a quella di una sezione appSettings di un file .config: un campo Section (varchar), Key (varchar), un campo Value (varchar) e in più un campo Type (varchar). Nel campo Section ho impostato il nome del tipo di cui creerò l'istanza, nel campo Key c'è il nome della proprietà, nel campo Value il valore che la proprietà deve assumere e nel campo Type il Type della proprietà (es. System.String, System.Int32, ecc.).
La prima cosa di cui si ha bisogno è un riferimento all'assembly che contiene la definizione del tipo che vogliamo istanziare: la classe [Assembly] dispone di un metodo shared (static in C#) che passando il nome dell'assembly restituisce un oggetto di tipo Assembly
Dim _assembly As [Assembly] = [Assembly].LoadFrom("Lanny.Assembly.dll")
A questo punto devo reperire le informazioni circa il tipo presente nell'assembly
Dim _myType As [Type] = _assembly.GetType("MioNamespace.MioTipo")
Avendo questi riferimenti sono pronto a scorrere il contenuto della tabella e impostare le proprietà dell'oggetto MioOggetto di tipo MioTipo (Dim MiaClasse as New MioTipo); nel mio caso scorro un SQLDataReader, ma come ho detto in precedenza può essere qualunque cosa...
With MySQLDataReader
Dim _myPorpertyInfo As PropertyInfo
Do While .Read = True
_myPropertyInfo = _myType.GetProperty(.Item("Key"))
_myPropertyInfo.SetValue(MioOggetto, .Item("Value"), Nothing)
Loop
End With
Se tutte le proprietà di MioTipo fossero di tipo System.String avremmo già finito, però se così non fosse bisogna trovare il modo di convertirle nel tipo giusto. Sfrutto la Reflection per ottenere un riferimento all'assembly mscorlib.dll (il Core del .NET Framework per intenderci, dove risiedono il namespace System e tutti i tipi del Framework); per evitare di andare a scrivere da qualche parte il percorso di installazione del Framework necessario per utilizzare [Assembly].LoadFrom() nel caso in cui l'assembly specificato non sia nell'application path, sfrutto un altro metodo shared (static in C#) del tipo [Assembly]: GetAssembly(value as System.Type).
'Questa correzione è stata apportata su suggerimento di Matteo: grazie 1000!
'Dim _SystemAssembly As [Assembly] = [Assembly].GetAssembly(GetType(String))
In pratica richiedo di referenziare l'assembly dove è definito il tipo String (cioé il mio mscorlib.dll)
Fatto ciò modifico il loop di prima come segue
With MySQLDataReader
Dim _myPorpertyInfo As PropertyInfo
Do While .Read = True
_myPropertyInfo = _myType.GetProperty(.Item("Key"))
Dim _val As New Object
_val = Convert.ChangeType(.Item("Value"), _myPropertyInfo.PropertyType) 'Vedi commento sopra
'_SystemAssembly.GetType(.Item("Type")))
_myPropertyInfo.SetValue(MioOggetto, _val, Nothing)
Loop
End With