Is there a way to dynamically execute code contained in a string using .net 2.0, in a similar way to eval() in javascript or using sp_executeSQL in tsql?
I have a st
I know you're after C# but the code I have for this is in VB. You could translate it easily enough using Developer Fusion's VB to C# converter. I used it on a project to allow users to add complex calculations into their application at runtime. It compiles their VB code into a library in memory and then runs the code returning the resulting output. It could be repurposed fairly easily for what you're attempting to do.
Imports System.Reflection
Imports System.CodeDom.Compiler
Imports System.Text.RegularExpressions
Imports System.Math
Module Module1
Function Evaluate(ByVal Expression As String, ByVal Args() As Object) As Object
If Expression.Length > 0 Then
'Replace each parameter in the calculation expression with the correct values
Dim MatchStr = "{(\d+)}"
Dim oMatches = Regex.Matches(Expression, MatchStr)
If oMatches.Count > 0 Then
Dim DistinctCount = (From m In oMatches _
Select m.Value).Distinct.Count
If DistinctCount = Args.Length Then
For i = 0 To Args.Length - 1
Expression = Expression.Replace("{" & i & "}", Args(i))
Next
Else
Throw New ArgumentException("Invalid number of parameters passed")
End If
End If
Dim FuncName As String = "Eval" & Guid.NewGuid.ToString("N")
Dim FuncString As String = "Imports System.Math" & vbCrLf & _
"Namespace EvaluatorLibrary" & vbCrLf & _
" Class Evaluators" & vbCrLf & _
" Public Shared Function " & FuncName & "() As Double" & vbCrLf & _
" " & Expression & vbCrLf & _
" End Function" & vbCrLf & _
" End Class" & vbCrLf & _
"End Namespace"
'Tell the compiler what language was used
Dim CodeProvider As CodeDomProvider = CodeDomProvider.CreateProvider("VB")
'Set up our compiler options...
Dim CompilerOptions As New CompilerParameters()
With CompilerOptions
.ReferencedAssemblies.Add("System.dll")
.GenerateInMemory = True
.TreatWarningsAsErrors = True
End With
'Compile the code that is to be evaluated
Dim Results As CompilerResults = _
CodeProvider.CompileAssemblyFromSource(CompilerOptions, FuncString)
'Check there were no errors...
If Results.Errors.Count > 0 Then
Else
'Run the code and return the value...
Dim dynamicType As Type = Results.CompiledAssembly.GetType("EvaluatorLibrary.Evaluators")
Dim methodInfo As MethodInfo = dynamicType.GetMethod(FuncName)
Return methodInfo.Invoke(Nothing, Nothing)
End If
Else
Return 0
End If
Return 0
End Function
End Module
I set up my dynamic code like this:
Dim Expr As String = " If ({0} < 20000) Then" & vbCrLf & _
" Return Max(15, Min(75,0.12*{0}))" & vbCrLf & _
" Else" & vbCrLf & _
" Return Max(75,0.05*{0})" & vbCrLf & _
" End If"
And then set up some arguments for the expression and execute:
Dim Args As New List(Of String)
While True
Dim Val As String = Console.ReadLine
Args.Clear()
If IsNumeric(Val) Then
Args.Add(Val)
Dim dblOut As Object = Evaluate(Expr, Args.ToArray)
Console.WriteLine(dblOut)
Else
Exit While
End If
End While