My Blog

Working with CodeDom

by lupok on martedì 29 gennaio 2013 14:41
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

Blogs Parent Separator My Blog
Author
lupok

My Blog

Tags