search
Twitter Rss Feeds
MicrosoftArticlesForumsGroups
C# .NET
VB.NET
Visual Studio .NET
ADO.NET
Xml/Xslt
VB 6.0
.NET CF
GDI+
LINQ
Deployment
Security
FoxPro
Silverlight / WPF
Entity Framework
RIA Services

Web ProgrammingArticlesForumsGroups
JavaScript
ASP
ASP.NET
Web Services

Non-MicrosoftArticlesForumsGroups
NHibernate
Perl
PHP
Ruby
Java
Linux / Unix
Apple
Open Source

DatabasesArticlesForumsGroups
SQL Server
Access
Oracle
MySQL
Other Databases

OfficeArticlesForumsGroups
Microsoft Excel
Microsoft Word
Microsoft Powerpoint
Publisher
Money

Operating SystemsArticlesForumsGroups
Windows 7
Windows Server
Windows Vista
Windows XP
Windows Update
MAC
Linux / UNIX

Server PlatformsArticlesForumsGroups
Share Point
BizTalk
Site Server
Exhange Server
IIS
Transaction Server

Graphic DesignArticlesForumsGroups
Macromedia Flash
Adobe PhotoShop
Microsoft Expression

OtherArticlesForumsGroups
Subversion / CVS
Ask Dr. Dotnetsky
Active Directory
Networking
Uninstall Virus
Job Openings
Reviews
Search Engines
Resumes

 
Build a Custom .NET "EVAL" Provider
By Peter A. Bromberg, Ph.D.
Printer - Friendly Version
Peter Bromberg

At work (my real job) today, an interesting discussion came up about how nice it is to be able to use the Windows Scripting Host Object Model and / or Javascript to parse and execute arbitrary strings of code "on the fly". The .NET Platform doesn't have, in any of the supported languages I've seen, an "EVAL" method to do this. However, after a little research, I found out that it's almost a trivial matter to "roll your own"!

The key built - in .NET classes with which this can be so easily achieved are the CodeProvider classes (VBCodeProvider and CSharpCodeProvider, for example) in the System.CodeDoMCompiler namespace. Two entire book chapters could be written about how to use these, along with Reflection, and some authors probably already have, so I leave the research to you. Here my objective is simply to illustrate how easily these namespaces and classes can be put to use for something truly useful.

Think about this: Your application does a lot of business logic, some of which requires complicated logical strings of code that may change over time to meet certain business conditions or metadata. Wouldn't it be great if you could pull the most current string of code to be run out of your database based on certain stored procedure input parameters, and be sure it's run and you get back the desired result? In fact, the returned string of code may even be dynamically created based on some of the input parameters from the sproc itself. . . Well, that's what this exercise is all about!.

Without further discussion, I present the basic framework for the class:

Imports Microsoft.VisualBasic
Imports System
Imports System.Text
Imports System.CodeDom.Compiler
Imports System.Reflection
Imports System.IO
Namespace PAB.Util
    Public Class EvalProvider
        Public Function Eval(ByVal vbCode As String) As Object
            Dim c As VBCodeProvider = New VBCodeProvider
            Dim icc As ICodeCompiler = c.CreateCompiler()
            Dim cp As CompilerParameters = New CompilerParameters

            cp.ReferencedAssemblies.Add("system.dll")
            cp.ReferencedAssemblies.Add("system.xml.dll")
            cp.ReferencedAssemblies.Add("system.data.dll")
            ' Sample code for adding your own referenced assemblies
            'cp.ReferencedAssemblies.Add("c:\yourProjectDir\bin\YourBaseClass.dll")
            'cp.ReferencedAssemblies.Add("YourBaseclass.dll")
            cp.CompilerOptions = "/t:library"
            cp.GenerateInMemory = True
            Dim sb As StringBuilder = New StringBuilder("")
            sb.Append("Imports System" & vbCrLf)
            sb.Append("Imports System.Xml" & vbCrLf)
            sb.Append("Imports System.Data" & vbCrLf)
            sb.Append("Imports System.Data.SqlClient" & vbCrLf)
            sb.Append("Namespace PAB  " & vbCrLf)
            sb.Append("Class PABLib " & vbCrLf)

            sb.Append("public function  EvalCode() as Object " & vbCrLf)
            'sb.Append("YourNamespace.YourBaseClass thisObject = New YourNamespace.YourBaseClass()")
            sb.Append(vbCode & vbCrLf)
            sb.Append("End Function " & vbCrLf)
            sb.Append("End Class " & vbCrLf)
            sb.Append("End Namespace" & vbCrLf)
            Debug.WriteLine(sb.ToString()) ' look at this to debug your eval string
            Dim cr As CompilerResults = icc.CompileAssemblyFromSource(cp, sb.ToString())
            Dim a As System.Reflection.Assembly = cr.CompiledAssembly
            Dim o As Object
            Dim mi As MethodInfo
            o = a.CreateInstance("PAB.PABLib")
            Dim t As Type = o.GetType()
            mi = t.GetMethod("EvalCode")
            Dim s As Object
            s = mi.Invoke(o, Nothing)
            Return s
        End Function
    End Class
End Namespace

What does it do? Well, it creates the CodeCompiler instance and the ICodeCompiler interface, sets it all up, and takes your input string (which needs to look just like valid code (VB.NET in this case, though its just as easy to use the CSharpCodeProvider). It creates a public method, EvalCode() with a return value of Object, compiles it, loads the compiled assembly into memory, and using Reflection, instantiates an instance and calls your method which is "wrapped' into the generic EvalCode method. It then returns the result (whatever Object that may be) and you are "good to go!".

An example of code that you could send into this method might be:

Dim strConn As String = "Server=(local);dataBase=Northwind;User id=sa;Password=;"
Dim cmd As New SqlCommand()
Dim cn As New SqlConnection(strConn)
cn.Open()
cmd.Connection = cn
cmd.CommandText = "select * from employees"
cmd.CommandType = CommandType.Text
Dim ds As DataSet = New DataSet()
Dim da As New SqlDataAdapter()
da.SelectCommand = cmd
da.Fill(ds)
Return ds

This code could come from your database, or wherever, and be dynamically assembled before you send it in. The downloadable solution has a Winforms test harness illustrating sample usage with the code snippet shown above, and uses it to populate a DataGrid on the form. Enjoy!

Download the code that accompanies this article

 

Peter Bromberg is a C# MVP, MCP, and .NET consultant who has worked in the banking and financial industry for 20 years. He has architected and developed web - based corporate distributed application solutions since 1995, and focuses exclusively on the .NET Platform. Pete's samples at GotDotNet.com have been downloaded over 41,000 times. You can read Peter's UnBlog Here.  --><--NOTE: Post QUESTIONS on FORUMS!

Do you have a question or comment about this article? Have a programming problem you need to solve? Post it at eggheadcafe.com forums and receive immediate email notification of responses.