1

我在动态编译用于 Silverlight 3.0 的 DLL 时遇到了困难。我的目标是采用我的用户提供的一些规则并将它们编译成一个 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。

4

1 回答 1

1

通过让代码提供者保存它正在创建的临时文件找到了答案。这是我添加的:

    parameters.TempFiles.KeepFiles = True

到编译器选项。

完成此操作后,vbc 命令行及其编译的代码将留在我的用户临时目录中。看着它,我可以看到我使用的是 .Net 2.0 目录中的 vbc 编译器,而不是 3.5 目录。

为了让它使用 3.5 目录中的编译器,'Compile 注释下的行更改为以下内容:

    ' 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

一旦正确设置,代码就会编译。

于 2009-10-14T14:00:40.073 回答