I am having difficulty dynamically compiling a DLL for use with Silverlight 3.0. My goal is to take some rules provided by my users and compile them into a DLL for custom editing purposes.
I created a Silverlight class library project in Visual Studio to get the command line for compiling a Silverlight class library. Based on that and the many examples for compiling VB using the VBCodeProvider, I came up with the following method for comping code in a string to a DLL:
Public Function Compile(ByVal code As String, ByVal assemblyName As String) As CompilerResults
' set the compiler parameters
Dim parameters As CompilerParameters = New CompilerParameters()
parameters.OutputAssembly = assemblyName
parameters.GenerateInMemory = False
parameters.GenerateExecutable = False
parameters.IncludeDebugInformation = True
' constants for the silverlight assembly directories
Dim sdkDir As String = "c:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\Silverlight\v3.0\"
Dim clientDir As String = "c:\Program Files (x86)\Microsoft SDKs\Silverlight\v3.0\Libraries\Client\"
Dim riaDir As String = "C:\Program Files (x86)\Microsoft SDKs\RIA Services\v1.0\Libraries\Silverlight\"
' set referenced assemblies
parameters.ReferencedAssemblies.Clear()
parameters.ReferencedAssemblies.Add(sdkDir + "mscorlib.dll")
parameters.ReferencedAssemblies.Add(sdkDir + "System.Core.dll")
parameters.ReferencedAssemblies.Add(sdkDir + "system.dll")
parameters.ReferencedAssemblies.Add(sdkDir + "System.Net.dll")
parameters.ReferencedAssemblies.Add(sdkDir + "System.Windows.Browser.dll")
parameters.ReferencedAssemblies.Add(sdkDir + "System.Windows.dll")
parameters.ReferencedAssemblies.Add(sdkDir + "System.Xml.dll")
' build compiler options for sdk path to point to Silverlight.
Dim options As String
options = "/sdkpath:""" + sdkDir + "\"" "
options = options + "/define:""SILVERLIGHT=1"""
parameters.CompilerOptions = options
' compile
Dim provider = New VBCodeProvider()
Return provider.CompileAssemblyFromSource(parameters, code)
End Function
My unit test class that code as follows:
Public Sub CompileTest()
' Assemble
Dim builder As StringBuilder = New StringBuilder()
builder.AppendLine("Imports System")
builder.AppendLine("Namespace Namespace1")
builder.AppendLine("Public Class Class1")
builder.AppendLine("Public Sub Test()")
builder.AppendLine("Console.WriteLine(""Hello Compilation"")")
builder.AppendLine("Console.ReadLine()")
builder.AppendLine("End Sub")
builder.AppendLine("End Class")
builder.AppendLine("End Namespace")
Dim assemblyName As String = ".\TestAssembly.dll"
' Act
Dim compiler As SilverlightCompiler = New SilverlightCompiler()
Dim cr As CompilerResults = compiler.Compile(builder.ToString(), assemblyName)
' Assert
Assert.AreEqual(0, cr.Errors.Count)
End Sub
This does not compile with the following error:
vbc : Command line (0,0) : error BC2010: compilation failed : 'Member 'IsNumeric' cannot be found in class 'Microsoft.VisualBasic.Information'. This condition is usually the result of a mismatched 'Microsoft.VisualBasic.dll'.'
I've looked and, in fact, the Silverlight version of the class Microsoft.VisualBasic.Information does not contain member IsNumeric. So I appear to be picking up the correct libraries using the sdkpath option. But I have no idea why I'm trying to call that method in the first place.
Can anyone shed light on how to successfully compile source code dynamically into a Silverlight compatible class library? TIA.
Found the answer by getting the code provider to save the temp files it was creating. This is done my adding:
to the compiler options.
When this was done, the vbc command line and the code it compiled was left behind in my user temp directory. Looking at it, I could see I was using the vbc compiler in the .Net 2.0 directory, not the 3.5 directory.
In order to get it to use the compiler in the 3.5 directory, the lines under the 'Compile comment were changed to the following:
It uses an overload on the VBCodeProvider constructor that takes language options. A co-worker found this using Reflector on the T4 template engine; later I found it documented in an example here:
http://msdn.microsoft.com/en-us/library/bb470844.aspx
Once this was set properly, the code compiled.