Hi and thanks for such an amazing project!
I'm someone who really tries to scour the internet to answer my questions, but I'm simply at a roadblock and was wondering if anyone has a code snippet that they can share.
Here's a simple example of what I'm trying to accomplish; for the purpose of this, MyList is a List<MyObject>:
var test = MyList.AsEnumerable().Where(c => c.Active).First().Description;
But I get a script error that System.Collections.Generic.IEnumerable<MyObject> does not contain a definition for 'Where'.
I tried adding this before the above line (based on some code snippet I found):
var EnumerableT = host.type("System.Linq.Enumerable", "System.Core");
I've also tried adding this in the engine init where I load up a variety of types/object:
E.AddHostType(typeof(System.Linq.Enumerable));
This isn't critical, and I can live without it, but it would be great if I could get this to work and I hope I'm just missing something.
Thanks!
Hello @roblarky,
Because it's built around strongly-typed callbacks, LINQ is not as natural a fit for JavaScript as it is for C#, but it's certainly usable, especially with JavaScript's arrow functions. We'll assume that you're using V8.
Let's use this simple version of your MyObject class:
``` C#
public class MyObject {
public bool Active;
public string Description;
}
Now let's expose a list to the script engine:
``` C#
engine.Script.MyList = new List<MyObject> {
new MyObject { Active = false, Description = "foo" },
new MyObject { Active = true, Description = "bar" },
new MyObject { Active = false, Description = "baz" },
new MyObject { Active = true, Description = "qux" }
};
Here's an example that demonstrates simple LINQ usage:
``` C#
engine.AddHostType(typeof(Enumerable));
engine.AddHostType("Pred", typeof(Func
engine.Execute(@"
var test = MyList.Where(new Pred(c => c.Active)).First().Description;
");
Console.WriteLine(engine.Script.test); // prints "bar"
Note that we had to expose the callback type to allow the script engine to construct the required delegate. We can simplify this by adding a JavaScript-friendly LINQ extension:
``` C#
public static class EnumerableExtensions {
public static IEnumerable<T> where<T>(this IEnumerable<T> source, dynamic pred) {
return source.Where(item => Convert.ToBoolean(pred(item)));
}
}
Now we can use LINQ in JavaScript as easily as in C#:
``` C#
engine.AddHostType(typeof(Enumerable));
engine.AddHostType(typeof(EnumerableExtensions));
engine.Execute(@"
var test = MyList.where(c => c.Active).First().Description;
");
Console.WriteLine(engine.Script.test); // prints "bar"
```
Obviously to use LINQ in a nontrivial application we'd have to expose many more callback types or extensions, but hopefully this gives you an idea of what's possible.
Good luck!
Thank you very much! This is exactly the nudge in the right direction I was looking for.
This nudged me in the right direction as well except I have found a more generic way of handling lambda functions. Instead of creating a new extension method for every LINQ function, one can use the following solution. It only requires exposing ExtendedHostFunctions and (optionally) exposing a helper method. Of course to actually use LINQ, you must expose Enumerable too.
engine.AddHostType("host", typeof(ExtendedHostFunctions));
engine.AddHostType(typeof(Enumerable));
engine.Execute("var $$ = (type, lambda) => host.func(host.type(type), 1, lambda);");
And then you can do magic like this:
Accounts.Sum($$('System.Int32', row=>row.Amount))
Considering that:
class Account
{
public int Amount { get; set; }
}
And your "context" object has a property:
public Account[] Accounts { get; set; }
Most helpful comment
Hello @roblarky,
Because it's built around strongly-typed callbacks, LINQ is not as natural a fit for JavaScript as it is for C#, but it's certainly usable, especially with JavaScript's arrow functions. We'll assume that you're using V8.
Let's use this simple version of your
MyObjectclass:``` C#
public class MyObject {
public bool Active;
public string Description;
}
Here's an example that demonstrates simple LINQ usage:
``` C#));
engine.AddHostType(typeof(Enumerable));
engine.AddHostType("Pred", typeof(Func
engine.Execute(@"
var test = MyList.Where(new Pred(c => c.Active)).First().Description;
");
Console.WriteLine(engine.Script.test); // prints "bar"
Now we can use LINQ in JavaScript as easily as in C#:
``` C#
engine.AddHostType(typeof(Enumerable));
engine.AddHostType(typeof(EnumerableExtensions));
engine.Execute(@"
var test = MyList.where(c => c.Active).First().Description;
");
Console.WriteLine(engine.Script.test); // prints "bar"
```
Obviously to use LINQ in a nontrivial application we'd have to expose many more callback types or extensions, but hopefully this gives you an idea of what's possible.
Good luck!