Roslyn VisualBasic.ScriptEngine doesnt recognize hostObject written on C#
-
16-06-2021 - |
سؤال
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#.
المحلول
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.
نصائح أخرى
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