String Compile

noviembre 25, 2008 :: Posted by - Emilio Torrens :: Category -

Con CSharpCodeProvider y  ICodeCompiler podemos escribir y ejecutar código al vuelo.

Cuando vi esto en una demo de Microsoft no me pareció algo excesivamente útil, pero estos días me he encontrado con un problema que he podido resolver gracias a esto.

Resulta que tengo un servicio al que le envían documentos XML y no tengo una manera fija para saber quien envía esos documentos, algunos es por el Document Element, otros por un valor de XPath, y cosas así, así que para resolverlo dejo que el usuario configure la condición y la compilo y la ejecuto.

Aquí dejo un ejemplo de código:

using System;
using System.CodeDom.Compiler;
using System.Reflection;
using System.Text;
using Microsoft.CSharp;

namespace Macros
{
    public interface IStrCode
    {
        bool Eval(string Condicion);
    }

    public class StrCodeManager
    {
        public static void Test()
        {
            bool result = IsValid("\"1234\".Length == 4");
            result = IsValid("2 + 2 == 5");
            result = IsValid("\"Hola Que tal\".IndexOf(\"Hola\") != 0");
        }

        public static bool IsValid(string Condicion)
        {
            string SourceString =
                @"using Macros;
                        public class StrCode : IStrCode
                        {
                            public bool Eval(string Condicion)
                            {
                                return @@Condicion@@;
                            }
                        }"
                    .Replace("@@Condicion@@", Condicion);

            CSharpCodeProvider codeProvider = new CSharpCodeProvider();
            ICodeCompiler icc = codeProvider.CreateCompiler();

            CompilerParameters parameters = new CompilerParameters();
            parameters.GenerateExecutable = false;
            //Aqui añadimos las referencias necesarias
            parameters.ReferencedAssemblies.Add("System.dll");
            //Esta es la referencia a esta dll para que tenga acceso al interface
            parameters.ReferencedAssemblies.Add("My.dll");
            CompilerResults results = icc.CompileAssemblyFromSource(parameters, SourceString);

            if (results.Errors.Count != 0)
            {
                StringBuilder stringBuilder = new StringBuilder();
                foreach (CompilerError CompErr in results.Errors)
                {
                    stringBuilder.AppendLine(CompErr.ErrorText);
                }

                throw new Exception(stringBuilder.ToString());
            }

            Assembly As = results.CompiledAssembly;

            foreach (Type tipo in As.GetTypes())
            {
                if (tipo.GetInterface("IStrCode") != null)
                {
                    IStrCode eval = (IStrCode) Activator.CreateInstance(tipo);
                    return eval.Eval(Condicion);
                }
            }

            throw new Exception("");
        }
    }
}

Si te gusta compartelo ...
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • DotNetKicks
  • Live
  • MySpace
  • Meneame
  • Twitter

Tags:

Leave a Reply