views:

204

answers:

8
+1  A: 

Although I do not recommend your approach at all, you can do what you want using Reflection.Emit. Here's a tutorial.

Randolpho
+1  A: 

Would you not be better to define a set of 'possible' constants that you could then parse for in your code and execute dynamically, rather than just any bit of C# that you get passed.

Paddy
+2  A: 

It looks like you need some kind of basic rules processor. There are a couple options for accomplishing what you need. Like Randolpho mentioned, you can use Reflection.Emit to generate lightweight IL code at runtime. Another alternative, if you have .NET 3.5, is to use Expression trees.

With the introduction of LINQ, Microsoft needed to add a basic expression engine to .NET that LINQ statements could be translated into during compilation. The expression library is not limited to supporting LINQ, however, and you should be able to write a basic parser that would turn your XML into an Expression tree. Each Expression tree can later be compiled into a delegate that may then be invoked, either synchronously or asynchronously.

You might find the following link useful if you do explore the Expression tree route:

http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

It provides a dynamic expression parser, which, while it doesn't fully support the expressions you have in your question, does support almost any other basic expressions.

jrista
+1  A: 

Do you really want to allow any C#?
If so you may want to look at this script engine for C#. Keep in mind, being able to run arbitrary code is a large security exposure.

If you are ok with waiting for .NET 4.0 (in beta now, release later this year), you can utilize the DLR, or Dynamic Language Runtime for this.

On the other hand if you don't want to rely on .NET 4.0 and you are willing to limit yourself, then you can use Reflection pretty simply. If you could confine yourself to, for example, methods on a DateTime instance, things would be simpler. This example shows how to invoke a method via reflection, on an instance of DateTime that is set to NOW.

  DateTime d = DateTime.Now;
  string logicToInvoke= "Now.AddDays(12)";
  string pattern = @"^Now\.(?<methodname>\w+)\((?<argstring>[^\)]*)\)";
  RGX.Match match = RGX.Regex.Match(logicToInvoke, pattern);

  // If match not found, logic is improperly formed.
  if (!match.Success)
  {
      Console.WriteLine("The DateTime method logic is improperly formed.");
      return;
  }

  // Store method and arg 
  string methodName = (string) match.Groups["methodname"].Value;
  string argString = (string) match.Groups["argstring"].Value;

  Console.WriteLine("Invoking method '{0}' with args '{1}'...", methodName, argString);
  System.Type t= d.GetType();

  try
  {
      switch (methodName)
      {

      case "AddDays" :
          int daysToAdd = System.Int32.Parse(argString);
          DateTime result = (DateTime) t.InvokeMember (methodName,
                                          System.Reflection.BindingFlags.Public | 
                                          System.Reflection.BindingFlags.Instance  |
                                          System.Reflection.BindingFlags.InvokeMethod , 
                                          null, d, new object [] {daysToAdd});

          Console.WriteLine("Result: {0}", result.ToString("yyyy/MM/dd"));
          break;
      default:
          Console.WriteLine("unsupported method: {0}", methodName);
          break;
      }

  }
  catch (System.Exception exc1)
  {
      Console.WriteLine("Exception while invoking method: {0}", exc1);
  }

I'd suggest keeping the format of the DateTime value separate from the value of it. The format of the time ("yy/MM/dd") might be better specified in an attribute, as with:

<Name>DateOne</Name>
<Value format="MM/dd/yy">[Now.AddDays(-1)]</Value>
Cheeso
A: 

you first need to create and compile a class with your code in it in memory, after it has been compiled you need to reflect against it and invoke the method in which your dynamic code lives, method could also return value.

here is a link to get you started Dynamic Code

Stan R.
A: 

Depending on what exactly you're trying to do, you may find some components from Spring .NET useful. have a look at Spring .NET Expressions.

For example:

(DateTime) ExpressionEvaluator.GetValue(null, "new DateTime(1974, 8, 24)")

where "new DateTime(1974,8,24)" is your text

Nader Shirazie
A: 

If you don't need C# syntax to the last comma, the easiest way to do this is probably by using a DLR language like IronPython. Google for "hosting ironpython" and you will find samples.

Niki
+2  A: 

CS-Script will do what you're looking for.

From one of their examples:

Assembly assembly = CSScript.LoadMethod(
        @"public static void PrintSum(int a, int b)
          {
              Console.WriteLine((a+b));
          }");

AsmHelper script = new AsmHelper(assembly);
script.Invoke("*.PrintSum", 1, 2);

That should be easy enough to do what you want. I'm using it for our rules engine (just switched from Boo), and it's great for dynamic code.

Chris Doggett