using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace CodeDOMExample
{
class Program
{
static void Main(string[] args)
{
// legge il file che contiene l'espressione
String script = System.IO.File.OpenText("TextFile1.txt").ReadToEnd();
// crea una nuova unità di compilazione
CodeCompileUnit targetUnit = new CodeCompileUnit();
// definisce il nuovo tipo
CodeTypeDeclaration targetClass =
new CodeTypeDeclaration("ScriptClass");
// definisce il namespace contenente la classe
CodeNamespace targetNamespace =
new CodeNamespace("AS.it");
// importa i namespace necessari
targetNamespace.Imports.Add(new CodeNamespaceImport("System"));
// dechiara che il tipo creato è una classe
targetClass.IsClass = true;
// imposta la visibilità della classe
targetClass.TypeAttributes = System.Reflection.TypeAttributes.Public;
// aggiunge la classe al namespace
targetNamespace.Types.Add(targetClass);
// aggiunge il namespace all'unità di compilazione
targetUnit.Namespaces.Add(targetNamespace);
// crea un cotruttore da aggiungere alla classe
CodeConstructor constructor = new CodeConstructor();
constructor.Attributes = MemberAttributes.Public |
MemberAttributes.Final;
// definizione di un campo privato all'interno della classe
String fieldName = "m_field1";
// crea un nuovo campo da inserire nella classe
CodeMemberField field1 = new CodeMemberField();
// imposta la visibilità del campo
field1.Attributes = MemberAttributes.Private;
// imposta il nome del campo
field1.Name = fieldName;
// imposta il tipo del campo
field1.Type = new CodeTypeReference(typeof(Int32));
// aggiunge il campo creato alla classe
targetClass.Members.Add(field1);
// aggiunta di parametri nel costruttore
String parameterName = "field1";
// crea un nuovo parametro defininendo il tipo ed il nome
constructor.Parameters.Add(new CodeParameterDeclarationExpression(typeof(Int32), parameterName));
// crea un riferimento tra il paremetro del costruttore ed un campo della classe
CodeFieldReferenceExpression fieldReference =
new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), fieldName);
// assegna il parametro aggiunto al costruttore al campo aggiunto in precedenza alla classe
constructor.Statements.Add(new CodeAssignStatement(fieldReference,
new CodeArgumentReferenceExpression(parameterName)));
// aggiunge il costruttore alla classe
targetClass.Members.Add(constructor);
// crea un nuovo metodo da aggiungere alla classe
CodeMemberMethod method = new CodeMemberMethod();
// nome del metodo
method.Name = "Execute";
// aggiunge un paramtro al metodo specificando il tipo ed il nome
method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(Int32), "par1"));
// tipo di ritorno del metodo
method.ReturnType = new CodeTypeReference(typeof(Int32));
// definisce il valore di ritorno del metodo attraverso la dichiarazione di un corpo per il metodo stesso
CodeMethodReturnStatement returnStatement =
new CodeMethodReturnStatement() { Expression = new CodeSnippetExpression(script) };
method.Statements.Add(returnStatement);
// imposta la visibilità del metodo
method.Attributes = MemberAttributes.Public | MemberAttributes.Final;
// aggiunge il metodo alla classe
targetClass.Members.Add(method);
// crea un compilatore csharp
CodeDomProvider provider = CodeDomProvider.CreateProvider("cs");
CompilerParameters parameters = new CompilerParameters();
// l'assembly viene genereato in memoria
parameters.GenerateInMemory = true;
parameters.CompilerOptions = "/t:library";
// aggiunge il riferimento agli assembly necessari
parameters.ReferencedAssemblies.Add("System.dll");
// stampa nella console il codice creato
using (StringWriter sourceWriter = new StringWriter())
{
provider.GenerateCodeFromCompileUnit(targetUnit, sourceWriter,
new CodeGeneratorOptions() { BracingStyle = "C" });
Console.WriteLine(sourceWriter.ToString());
}
// compila il codice creato
CompilerResults results = provider.CompileAssemblyFromDom(parameters, targetUnit);
// se ci sono errori stampa nella console il testo degli errori
if (results.Errors.HasErrors)
{
foreach (CompilerError error in results.Errors)
Console.WriteLine(error.ErrorText);
}
else
{
System.Reflection.Assembly assembly = results.CompiledAssembly;
Type instanceType = assembly.GetType("AS.it.ScriptClass");
// crea una istanza della classe creato
Object instance = Activator.CreateInstance(instanceType, 4563);
// ottiene il metodo aggiunto alla classe
System.Reflection.MethodInfo scriptMethod = instanceType.GetMethod("Execute");
// imvoca il metodo e stampa il risultato
Console.WriteLine("Script method result: {0}", scriptMethod.Invoke(instance, new Object[] { 10 }));
Console.WriteLine("Press Enter to exit");
Console.ReadLine();
}
provider.Dispose();
}
}
}
CodeDOMExample.zip