我无法动态编译DLL以用于Silverlight 3.0。我的目标是采用我的用户提供的一些规则,并将它们编译成DLL以进行自定义编辑。
我在Visual Studio中创建了一个Silverlight类库项目,以获取用于编译Silverlight类库的命令行。基于此以及使用VBCodeProvider编译VB的许多示例,我想出了以下方法,用于将字符串中的代码编译为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
我的单元测试类代码如下:
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
这不会编译时出现以下错误:
vbc:命令行(0,0):错误BC2010:编译失败:在“Microsoft.VisualBasic.Information”类中找不到“成员'IsNumeric'。这种情况通常是由于'Microsoft.VisualBasic.dll'不匹配造成的。'
我看过,事实上,类Microsoft.VisualBasic.Information的Silverlight版本不包含成员IsNumeric。所以我似乎正在使用sdkpath选项获取正确的库。但我不知道为什么我试图首先调用该方法。
有人能说明如何成功地将源代码动态编译到Silverlight兼容的类库中吗? TIA。
答案 0 :(得分:1)
通过让代码提供程序保存它正在创建的临时文件找到答案。这是我添加的:
parameters.TempFiles.KeepFiles = True
到编译器选项。
完成此操作后,vbc命令行及其编译的代码将留在我的用户临时目录中。看着它,我可以看到我在.Net 2.0目录中使用的是vbc编译器,而不是3.5目录。
为了让它在3.5目录中使用编译器,“编译注释”下的行更改为以下内容:
' compile
Dim languageOptions As Dictionary(Of String, String) = New Dictionary(Of String, String)()
languageOptions("CompilerVersion") = "v3.5"
Dim provider = New VBCodeProvider(languageOptions)
Return provider.CompileAssemblyFromSource(parameters, code)
它在VBCodeProvider构造函数上使用了一个带有语言选项的重载。一位同事在T4模板引擎上使用Reflector发现了这一点;后来我发现它在一个例子中记录了:
http://msdn.microsoft.com/en-us/library/bb470844.aspx
一旦设置正确,代码就会编译。