4

我们的项目需要能够有一个简单的业务规则,我们的客户可以在 Visual basic 中编写脚本。虽然我们的主程序是用 C# 编写的

客户想要执行的脚本可能是这样的(我正在考虑最简单的情况)

var vbCode = @"
    If (Row.Code = 12) Then 
        Row.MappedCode = 1
    End If";

所以我在 C# 中创建了一个带有 Code 和 MappedCode 属性的 RowData 类

namespace ScriptModel
{
    public class RowData
    {
        public int Code { get; set; }
        public int MappedCode { get; set; }
    }
}

我创建了一个简单的主机对象类,例如

namespace ScriptModel
{
    public class HostObjectModel
    {
        public RowData Row { get; set; }

    }
}

使用 Roslyn.Scripting.VisualBasic.ScriptEngine 我创建一个引擎,创建一个带有 HostObjectModel 实例的会话并执行 engine.Execute(vbCode, session)

   var hostObj = new HostObjectModel();

   hostObj.Row = new RowData();
   hostObj.Row.Code = 12;

   var engine = new Roslyn.Scripting.VisualBasic.ScriptEngine(
                    new Assembly[] {hostObj.GetType().Assembly},
                    new string[] {"ScriptModel"} );

   var session = Session.Create(hostObj);

   engine.Execute(vbCode , session); 

它告诉我

(2,25):错误 BC30451:未声明“行”。由于其保护级别,它可能无法访问。

但是如果我在 C# 上创建类似的代码片段

 var csharpCode = @"
                    if (Row.Code == 12) 
                    {  
                        Row.MappedCode = 1;
                    };";

并使用 CSharp.ScriptEngine 一切都会正常工作

那么,有什么问题,为什么 VisualBasic.ScriptEngine 看不到用 C# 编译的类的公共属性,我认为应该是基于相同的 MSIL 语言,还是我错了?


更新:我安装了 Visual Basic 并在 VB 上创建了 ScriptModel 库。我还在类声明和 vbCode 中用 Row() 函数替换了 Row 属性。都没有帮助。:( 当我从 C# 运行 VisualBasic.ScriptEngine 时,它​​似乎根本不起作用。

4

2 回答 2

3

对于 VB 脚本,我发现您必须在脚本开头包含以下内容:

Imports ScriptModel

我想您可以自动将上述内容附加到代码字符串中,这样您的用户就不需要记住包含它。

当作为 ScriptEngine 创建的一部分添加时,我无法让它工作。之后使用以下方法似乎也不起作用:

engine.ImportedNamespaces.Append("ScriptModel");

尽管事后 ImportedNamespaces 计数为 1。但使用 c#,您似乎根本不需要导入命名空间。

于 2012-06-30T03:28:20.647 回答
1

我接受了先前的答案,因为它确实让我知道了如何使 VB.NET 脚本工作,但是 HostObject 仍然无法工作

所以实际的解决方法包括两个步骤

1) 在 VB 代码中使用 Imports ScriptModel

var vbCode = @"Imports ScriptModel

    If (Row.Code = 12) Then 
        Row.MappedCode = 1
    End If";

2) 不要使用 HostObject。将 Row 定义为公共静态类

namespace ScriptModel
{
    public static class Row
    {
        public static int Code { get; set; }
        public static int MappedCode { get; set; }
    }
}

我相信 MS 论坛上的答案也是正确的,当前版本的 HostObject 不支持http://social.msdn.microsoft.com/Forums/en-US/roslyn/thread/89970f0b-1c1c-47da-a180-9c4710abc4b9 VB,不过希望下个版本支持

于 2012-07-04T13:52:45.540 回答