Question

Our project need ability to have a simple business rules our customers can script in Visual basic. While our main program is written on C#

The script which customers want to execut could be like this (I am considering the simpliest possible case)

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

So I created a RowData class in C# with Code and MappedCode properties

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

I created a simple host object class like

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

    }
}

Using Roslyn.Scripting.VisualBasic.ScriptEngine I create an engine, create a session with an instance of HostObjectModel and perform 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); 

And it tells me that

(2,25): error BC30451: 'Row' is not declared. It may be inaccessible due to its protection level.

But if I create the similar code snippet on C#

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

and use CSharp.ScriptEngine it all will work correctly

So, what is a problem, why VisualBasic.ScriptEngine not able to see public properties of the class which was compiled in C#, it should be, I think, based on the same MSIL language or I am wrong?


Update: I installed Visual Basic and created ScriptModel library on VB. I also replaced Row property with Row() function both in class declaration and in vbCode. Neither helped. :( seems that VisualBasic.ScriptEngine doesnt work at all when I run it from C#.

Was it helpful?

Solution

For VB scripting I found you have to include the following at the start of the script:

Imports ScriptModel

I guess you could automatically pre-pend the above to the code string so your users don't need to remember to include it.

I have not been able to get it to work when added as part of the ScriptEngine creation. It also doesn't seem to work afterwards by using:

engine.ImportedNamespaces.Append("ScriptModel");

This is despite the fact that afterwards the ImportedNamespaces count is 1. With c# you don't seem to need to import the namespace at all.

OTHER TIPS

I accepted the previous answer because it really gave me an idea how to make VB.NET script work, however HostObject still doesnt work

So actual workaround consists of 2 steps

1) Use Imports ScriptModel in VB code

var vbCode = @"Imports ScriptModel

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

2) Do not use HostObject. Define Row as public static class

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

I believe that answer on MS forum is also correct, http://social.msdn.microsoft.com/Forums/en-US/roslyn/thread/89970f0b-1c1c-47da-a180-9c4710abc4b9 in current version HostObject is not supported for VB, but I hope it will be supported in next version

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top