The Pragmatic Programmer

Tulisan iseng kalo ada waktu.
See also: Other Geeks@INDC

Dynamic Business Rules

The requirements of my current projects states of changing business rules at runtime, well, actually I must build a feature like SAP validation and substition feature. First, I implemented it using Windows Workflow Foundation and then doing a stress test to it, but too bad the test results is not adequate, it slow.

I have to find another solution for it.

I need a way to add scripting to the application and the scripting mechanism must have feature to read my outside object. There are many ways to do it in .Net one of it is using CodeDomProvider to compile the code and generate assembly dynamically.

Because the person that has to modify the code is not a programmer so the language chosen must be the easiest one, so I pick VB language as the language. You can find the source program below.

Program.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;

namespace ConsoleApplication2
{
   class Program
  {
     static void Main(string[] args)
    {
      VBCompiler compiler = new VBCompiler();

      StringBuilder sb = new StringBuilder();
      sb.AppendLine("Imports System");
      sb.AppendLine("Imports System.Windows.Forms");
      sb.AppendLine("Imports DomainModel");
      sb.AppendLine("Public Class Test");
      sb.AppendLine("Public Shared Sub Main()");
      sb.AppendLine("DomainModel.Class1.Test()");
      sb.AppendLine("End Sub");
      sb.AppendLine("End Class");
      System.Reflection.Assembly asm = compiler.Compile(sb.ToString());
      ExecuteEntryPoint(asm, "Main");
      Console.ReadLine();
    }

private static int ExecuteEntryPoint(System.Reflection.Assembly assembly, string entryPoint)
{
      try
     {
      if (assembly != null)
      {
         Module[] mods = assembly.GetModules(false);
        Type[] types = mods[0].GetTypes();

        foreach (Type type in types)
       {
            MethodInfo mi = type.GetMethod(entryPoint, BindingFlags.Public  
                                                                           | BindingFlags.Static);
             if (mi != null)
                  mi.Invoke(null, null);
       }
     }
    }
    catch (Exception ex)
    {
       Console.WriteLine(ex.ToString());
     }
}

VBCompiler.cs

using System;
using System.Collections.Generic;
using System.Text;

using System.Reflection;
using System.CodeDom;
using System.CodeDom.Compiler;
using Microsoft.VisualBasic;

namespace ConsoleApplication2
{
    public class VBCompiler
   {
     private CodeDomProvider _codeProvider = new VBCodeProvider();
     public CompilerErrorCollection Errors = new CompilerErrorCollection();

     public Assembly Compile(string SourceCode)
    {
       ICodeCompiler compiler = _codeProvider.CreateCompiler();

       CompilerParameters compilerParams = new CompilerParameters();
       compilerParams.CompilerOptions = "/target:library /optimize"
       compilerParams.GenerateExecutable = false;
       compilerParams.GenerateInMemory = true;
       compilerParams.IncludeDebugInformation = false;
       compilerParams.ReferencedAssemblies.Add("mscorlib.dll");
       compilerParams.ReferencedAssemblies.Add("System.dll");
       compilerParams.ReferencedAssemblies.Add
                    ("System.Windows.Forms.dll");

       //Uncomment this code if you need to reference outside assembly.
       //The assembly must reside in the same folder as the application folder
       //compilerParams.ReferencedAssemblies.Add(@"DomainModel.dll");

       CompilerResults results = compiler.CompileAssemblyFromSource 
       (compilerParams, SourceCode);

       if (results.Errors.Count > 0)
      {
         foreach (CompilerError error in results.Errors)
            Errors.Add(new CompilerError(error.FileName, error.Line,
                     error.Column, error.ErrorNumber, error.ErrorText));
         return null;
       }
      
       Assembly generatedAssembly = results.CompiledAssembly;

       return generatedAssembly;
    }
  }
}

Share this post: | | | |

Comments

norman said:

Playing with CodeDom? :) You just move up to a higher level programmer. Congrats!

# July 16, 2007 1:58 PM