Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.
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 }
Notice that the class name of the class to be compiled is "EvalClass" and the inner method of the class is "Evaluate". Calling the "Evaluate()" method requires you to execute the following lines of code.
1 var parser = newInlineParser(subExpression, funcArgs, Arguments.Document, lang);
2 parser.init();
3 retString = parser.Evaluate();
Manish
Remember Me
a@href@title, strike