Closed cronoxyd closed 1 year ago
Hello @cronoxyd,
Thanks for posting your sample code. Our observations:
SampleData = "abc"
doesn't compile, because SampleData
is of type byte
rather than string
.inst
aren't visible in script code, because SampleClass
is internal
.System.String.Contains
isn't available in script code, because .NET strings are converted to JavaScript strings.If SampleClass
were public
, the following would work:
var sampleInst = new SampleClass { Name = "abc" };
eng.AddHostObject("inst", sampleInst);
Console.WriteLine(eng.Evaluate("inst.Name.includes('b')"));
Alternatively, if SampleClass
must remain internal
, you could do this:
var sampleInst = new SampleClass { Name = "abc" };
eng.AddHostObject("inst", HostItemFlags.PrivateAccess, sampleInst);
Console.WriteLine(eng.Evaluate("inst.Name.includes('b')"));
Good luck!
Thanks for the quick reply! First of all apologies about the wrong assignment, I condensed that code from a larger testing suite and I am actually assigning to Name
, not SampleData
. And with your suggestions, my code works fine now. I was operating under the assumption that exposed objects and their members are strictly kept on the C# side in terms of the API.
Out of curiosity: If I rather wanted to use the .NET string implementation (or at least its members) than the Javascript one, could I force ClearScript to keep the .NET implementation?
Hi @cronoxyd,
If I rather wanted to use the .NET string implementation (or at least its members) than the Javascript one, could I force ClearScript to keep the .NET implementation?
There's no way to suppress string conversion globally. Using ClearScript would be very painful (if not impossible) without automatic conversion of fundamental data types.
However, you can use host variables to selectively expose .NET's string implementation. Here's an example that adds several .NET members to JavaScript's string prototype:
dynamic setup = eng.Evaluate(@"(function (host) {
const toClr = str => host.newVar(str.valueOf());
const clrMembers = [ 'Length', 'Contains', 'Insert', 'Remove' ];
for (let name of clrMembers) {
Object.defineProperty(String.prototype, name, {
get: function() { return toClr(this)[name]; }
});
}
})");
setup(new HostFunctions());
With this setup in place, you can do things like this:
eng.AddHostType(typeof(Console));
eng.Execute(@"
const str = 'a story';
Console.WriteLine(str.Contains('to'));
Console.WriteLine(str.Insert(2, 'likely '));
");
Note that this isn't very efficient, as each invocation of a .NET string member involves a string copy and several hops across the boundary to the host.
Cheers!
Okay definitely looks like a only-when-you-have to thing. Still good to know just in case. Thank you so much for taking the time to write the examples!
Kind regards,
cronoxyd
I'm currently struggling with the issue that all properties of exposed host objects return
[undefined]
when my script tries to access them and I can't figure out why. Here's my code:I've also tried exposing the object using the
Script
property of the engine but to no avail. Thanks in advance!