4

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#.

Bogdan_Ch
  • 3,328
  • 4
  • 23
  • 39
  • Did you add a reference to the assembly that contains `HostObjectModel` and `RowData` to the `ScriptEngine`? Could you show us relevant parts of the code that creates and uses the engine? – svick Jun 22 '12 at 15:43
  • 2 svick - I added relevant code. HostObjectModel and RowData created in a separate assembly in a ScriptModel namespace... basically if this would be a problem with references or some error in the code, then it should not work either in VisualBasic.ScriptEngine or CSharp.ScriptEngine... but in my case it works with CSharp.ScriptEngine but doesnt with VisualBasic.ScriptEngine – Bogdan_Ch Jun 24 '12 at 09:18
  • I also posted it on MS forum http://social.msdn.microsoft.com/Forums/en-US/roslyn/thread/89970f0b-1c1c-47da-a180-9c4710abc4b9 . I am using “Roslyn” June 2012 CTP – Bogdan_Ch Jun 24 '12 at 09:45
  • Which VB.NET version do you have? – kol Jun 24 '12 at 10:18
  • Microsoft.VisualBasic.dll version 10.0.0.0, runtime version v4.0.30319 – Bogdan_Ch Jun 24 '12 at 10:43
  • One note: I have VB runtime as part of .NET 4.0 and I have SP1 for VS 2010. but I didnt install full Visual Basic language feature for VS 2010... I had only C# and F#... seems that I need to waste some time now and install VB and then install SP1 after it and simply compile my ScriptModel assembly in VB and try again. – Bogdan_Ch Jun 24 '12 at 10:56
  • This is an answer I got on MS forum: The VisualBasic support for scripting is only partially implemented at the moment. Many of the special binding rules that apply only in scripting contexts are not yet implemented. I'm not positive, but I don't think VB has any support for Host Objects yet, no matter what language they are implemented in. – Bogdan_Ch Jun 26 '12 at 09:55

2 Answers2

3

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.

Michael
  • 8,891
  • 3
  • 29
  • 42
1

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

Bogdan_Ch
  • 3,328
  • 4
  • 23
  • 39