Roslyn Visual Basic.ScriptEngine无法识别在C#上编写的主机对象

时间:2012-06-22 15:11:18

标签: c# vb.net scriptengine roslyn

我们的项目需要具备简单的业务规则,我们的客户可以在Visual Basic中编写脚本。虽然我们的主程序是用C#编写的

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

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

所以我使用Code和MappedCode属性在C#中创建了一个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根本不起作用。

2 个答案:

答案 0 :(得分:3)

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

Imports ScriptModel

我猜你可以自动将上面的内容预先添加到代码字符串中,这样你的用户就不需要记得包含它了。

作为ScriptEngine创建的一部分添加时,我无法使其工作。之后似乎也没有使用:

engine.ImportedNamespaces.Append("ScriptModel");

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

答案 1 :(得分: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论坛上的答案也是正确的,当前版本的http://social.msdn.microsoft.com/Forums/en-US/roslyn/thread/89970f0b-1c1c-47da-a180-9c4710abc4b9不支持VB,但我希望它能在下一版本中得到支持