Oggi mi sono trovato per
la prima volta a creare delle classi on-the-fly ereditando da una classe base ed
estendendo in base a delle informazioni passate.
Benché ci siano già
parecchi esempi in rete (che comunque ho fatto parecchia fatica a trovare) posto
anche il mio esempio che é arricchito di una piccola funzione per aggiungere i
riferimenti in maniera semplice.
Dim provider As Microsoft.VisualBasic.VBCodeProvider
Dim compiler As System.CodeDom.Compiler.ICodeCompiler
Dim results As System.CodeDom.Compiler.CompilerResults
'Impostazioni di compilazione
Dim cp As New System.CodeDom.Compiler.CompilerParameters
cp.GenerateInMemory = True 'Non mi interessa salvare su disco
cp.TreatWarningsAsErrors = False
cp.ReferencedAssemblies.Add("System.dll")
AddReferences(cp, GetType(TipoUtilizzatoDalCodiceGenerato))
Try
provider = New Microsoft.VisualBasic.VBCodeProvider
compiler = provider.CreateCompiler
results = compiler.CompileAssemblyFromSource(cp, CodiceGenerato)
If results.Errors.Count = 0 Then
Dim Ass As System.Reflection.Assembly = results.CompiledAssembly
Dim GeneratedType as Type = Ass.GetType("GeneratedType")
'Creo un'istanza del tipo appena creato
Dim O As Object = Activator.CreateInstance(Me.GeneratedType)
'Inserire qui il codice che usa il nuovo oggetto!
Else
'Errore di compilazione!
End If
Catch ex As System.Exception
'Attenzione: qualcosa é andato storto: il compilatore non dovrebbe
'sollevare eccezioni normalmente, ma al massimo riportare errori di
'compilazione in: results.Errors
End Try
Private Sub AddReferences(ByVal cp As System.CodeDom.Compiler.CompilerParameters, ByVal type As System.Type)
For Each M As System.Reflection.Module In type.Assembly.GetModules()
cp.ReferencedAssemblies.Add(M.Name)
Next M
'Analisi tipo base
If Not type.BaseType Is GetType(System.Object) Then
AddReferences(cp, type.BaseType)
End If
'Analisi interfacce
For Each T As Type In type.GetInterfaces
AddReferences(cp, T)
Next T
End Sub