A day in the life...

public class GeekEarth : Earth { }
posts - 14, comments - 24, trackbacks - 0

Wednesday, May 19, 2010

Embedding IronPython into a C# application

It’s been a while since I blogged, I’ve been busy :)

A requirement I have in an app I am writing is to allow the administrator to set up formulas which can be calculated at runtime. The client app is completely disconnected from Enterprise Core Objects, it uses a (query/command)->response approach so I didn’t want to expose OCL on the client, I also didn’t want to use OCL because I didn’t want arbitrary browsing of the model.

So I have been looking at IronPython – and I like it! I’m not going to go into details of what this code does, I’m just going to paste it so that you may take a look. In short the requirement is for the Admin to be able to retrieve values from the DB by name and perform whatever logic they wish in order to return a decimal result.

You need to reference the following DLLs.

Microsoft.Scripting
Microsoft.Scripting.Core
IronPython

And here is the source example

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using IronPython.Hosting;
using IronPython.Runtime;
using IronPython;
using Microsoft.Scripting.Hosting;
using Microsoft.Scripting;

namespace ConsoleApplication17
{
  class ConsoleApplication17
  {
    [STAThread]
    static void Main(string[] rawArgs)
    {
      var engine = Python.CreateEngine();
      var scriptSource = engine.CreateScriptSourceFromString(@"
def foo(paygroup):
  global retrievedValue
  global factor
  retrievedValue = numbers.GetValue(paygroup)
  if retrievedValue >= 100000:
    factor = 0.75
  elif retrievedValue >= 50000:
    factor = 0.8
  else:
    factor = 0.9
  return retrievedValue * factor"
        , SourceCodeKind.Statements);

      //Create a variable which can be used in the script
      //to retrieve values from the DB
      var scope = engine.CreateScope();
      scope.SetVariable("numbers", new Meh());

      //Compile the script
      scriptSource.Execute(scope);

      //Get a reference to the function
      Func<string, decimal> foo = scope.GetVariable<Func<string, decimal>>("foo");

      //Execute it
      Console.WriteLine(foo("a"));
      Console.WriteLine(foo("b"));
      Console.WriteLine(foo("c"));
      Console.ReadLine();
    }
  }

  public interface IMeh
  {
    int GetValue(string name);
  }

  public class Meh : IMeh
  {
    public int GetValue(string name)
    {
      switch (name)
      {
        case "a": return 100000;
        case "b": return 50000;
        default: return 36000;
      }
    }
  }

}

posted @ Wednesday, May 19, 2010 3:00 PM | Feedback (2) |

Powered by: