Noviembre 25, 2008 :: Posted by - Emilio Torrens :: Category -
C#
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("");
}
}
}