In this section I would like to demonstrate how to compile a .NET code on the fly. The code has been written in C#. It contains a class "InlineParser" which does the main job. It mainly, defines the class, does in-memory compilation and exposes a method for the execution of an inner method defined in the class. It also supports a choice of language whether C# or VB.NET for compilation.
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using Microsoft.CSharp;
6 using Microsoft.VisualBasic;
7 using System.CodeDom.Compiler;
8 using System.Reflection;
9 using System.Xml.Linq;
10
11 namespace com.eforceglobal.crux.bre
12 {
13 internalclassInlineParser
14 {
15 string expression = string.Empty;
16 string functionArguments = string.Empty;
17 string language = "CSharp";
18 XDocument paramList = null;
19 object objBase = null;
20
21 public InlineParser(string expr, string functionArgs, XDocument parameters, string lang)
22 {
23 expression = expr;
24 functionArguments = functionArgs;
25 paramList = parameters;
26 language = lang;
27 }
28
29 publicbool init()
30 {
31 if(language.ToLower().Equals("csharp"))
32 return InitCSharp();
33 else
34 return InitVB();
35 }
36
37 internalbool InitCSharp()
38 {
39 // Compile the expression in a class on the fly
40 CSharpCodeProvider cp = newCSharpCodeProvider(
41 newDictionary<string, string>() { { "CompilerVersion", "v3.5" } } );
42
43 //ICodeCompiler ic = cp.CreateCompiler();
44 CompilerParameters cparam = newCompilerParameters();
45 cparam.GenerateInMemory = true;
46 cparam.GenerateExecutable = false;
47
48
49 // Reference Assembly
50 cparam.ReferencedAssemblies.Add( "system.dll" );
51 cparam.ReferencedAssemblies.Add( "mscorlib.dll" );
52 cparam.ReferencedAssemblies.Add( "System.Core.dll" );
53 cparam.ReferencedAssemblies.Add( "System.Xml.dll" );
54 cparam.ReferencedAssemblies.Add( "System.Xml.Linq.dll" );
55
56
57 // Write your code
58 StringBuilder sb = newStringBuilder();
59 sb.Append( "using System;\n" );
60 sb.Append( "using System.Collections;\n" );
61 sb.Append( "using System.Collections.Generic;\n" );
62 sb.Append( "using System.Text;\n" );
63 sb.Append( "using System.Text.RegularExpressions;\n" );
64 sb.Append( "using System.Reflection;\n" );
65 sb.Append( "using System.Linq;\n" );
66 sb.Append( "using System.Xml.Linq;\n" );
67
68 sb.Append( "namespace com.eforceglobal.crux.bre {\n" );
69 sb.Append( "public class EvalClass {\n" );
70 sb.Append( "public EvalClass(){}\n" );
71 sb.Append( "public object Evaluate(\n" );
72 sb.Append( functionArguments ).Append( " ) {\n" );
73 sb.Append( expression ).Append("\n");
74 sb.Append( "}\n}\n}" );
75
76 //Console.WriteLine( sb.ToString() );
77
78 string code = sb.ToString();
79 CompilerResults cres = cp.CompileAssemblyFromSource( cparam, code );
80
81 // Compilation Unsuccessfull
82 StringBuilder errors = newStringBuilder();
83 foreach ( CompilerError cerr in cres.Errors )
84 errors.Append( cerr.ErrorText );
85
86 if ( cres.Errors.Count > 0 )
87 thrownewException( errors.ToString() );
88
89 // Compilation Successfull
90 if ( cres.Errors.Count == 0 && cres.CompiledAssembly != null )
91 {
92 Type ClsObj = cres.CompiledAssembly.GetType( "com.eforceglobal.crux.bre.EvalClass" );
93 try
94 {
95 if ( ClsObj != null )
96 {
97 objBase = Activator.CreateInstance( ClsObj );
98 }
99 }
100 catch ( Exception ex )
101 {
102 throw;
103 }
104 returntrue;
105 }
106 else
107 returnfalse;
108 }
109
110 internalbool InitVB()
111 {
112 // Compile the expression in a class on the fly
113 VBCodeProvider vb = newVBCodeProvider(
114 newDictionary<string, string>() { { "CompilerVersion", "v3.5" } } );
115
116 //ICodeCompiler ic = cp.CreateCompiler();
117 CompilerParameters cparam = newCompilerParameters();
118 cparam.GenerateInMemory = true;
119 cparam.GenerateExecutable = false;
120
121
122 // Reference Assembly
123 cparam.ReferencedAssemblies.Add( "system.dll" );
124 cparam.ReferencedAssemblies.Add( "mscorlib.dll" );
125 cparam.ReferencedAssemblies.Add( "System.Core.dll" );
126 cparam.ReferencedAssemblies.Add( "System.Xml.dll" );
127 cparam.ReferencedAssemblies.Add( "System.Xml.Linq.dll" );
128
129
130 // Write your code
131 StringBuilder sb = newStringBuilder();
132 sb.Append( "Imports System\n" );
133 sb.Append( "Imports System.Collections\n" );
134 sb.Append( "Imports System.Collections.Generic\n" );
135 sb.Append( "Imports System.Text\n" );
136 sb.Append( "Imports System.Text.RegularExpressions\n" );
137 sb.Append( "Imports System.Reflection\n" );
138 sb.Append( "Imports System.Linq\n" );
139 sb.Append( "Imports System.Xml.Linq\n" );
140
141 sb.Append( "Namespace com.eforceglobal.crux.bre \n" );
142 sb.Append( "Public Class EvalClass \n" );
143 sb.Append( "Public Function Evaluate ( " );
144 sb.Append( functionArguments ).Append(" ) As Object\n");
145 sb.Append( expression ).Append( "\n" );
146 sb.Append( "End Function\n" );
147 sb.Append( "End Class\n" );
148 sb.Append( "End Namespace" );
149
150 //Console.WriteLine( sb.ToString() );
151
152 string code = sb.ToString();
153 CompilerResults cres = vb.CompileAssemblyFromSource( cparam, code );
154
155 // Compilation Unsuccessfull
156 StringBuilder errors = newStringBuilder();
157 foreach ( CompilerError cerr in cres.Errors )
158 errors.Append( cerr.ErrorText );
159
160 if ( cres.Errors.Count > 0 )
161 thrownewException( errors.ToString() );
162
163 // Compilation Successfull
164 if ( cres.Errors.Count == 0 && cres.CompiledAssembly != null )
165 {
166 Type ClsObj = cres.CompiledAssembly.GetType( "com.eforceglobal.crux.bre.EvalClass" );
167 try
168 {
169 if ( ClsObj != null )
170 {
171 objBase = Activator.CreateInstance( ClsObj );
172 }
173 }
174 catch ( Exception ex )
175 {
176 throw;
177 }
178 returntrue;
179 }
180 else
181 returnfalse;
182 }
183
184 publicstring Evaluate()
185 {
186 string result = string.Empty;
187 Type type = objBase.GetType();
188 MethodInfo mInfo = type.GetMethod( "Evaluate" );
189
190 if ( mInfo != null )
191 {
192 ParameterInfo[] pInfo = mInfo.GetParameters();
193 object[] arguments = null;
194 if(pInfo!=null) arguments = newobject[pInfo.Length];
195 if ( pInfo != null )
196 {
197 foreach(ParameterInfo p in pInfo )
198 if ( paramList.Element( "arguments" ).Elements( p.Name ) != null )
199 {
200 arguments[p.Position] = (paramList.Element( "arguments" )
201 .Elements( p.Name ).Single().Value);
202 }
203 if ( pInfo.Length != arguments.Length )
204 thrownewArgumentException( "Insufficient parameters." );
205 }
206
207 result = mInfo.Invoke( objBase, arguments ).ToString();
208 }
209
210 return result;
211 }
212 }
213 }