Hi again,
Unfortunately ambiguity prevents automatic conversion of script functions to delegates, especially when generics are involved.
For example, examining a JavaScript function gets us, at best, a
parameter count, and while that might be enough to select the correct overload of
Where()
, it can't help us bind to the intended specialization of something like
Select()
, where the delegate's return type plays a critical role in finding the right method. To invoke
Select()
successfully we must either have explicit type arguments or a strongly-typed delegate; lacking both it's just not possible.
However, there are things you can do to make LINQ easier for script code to use. For example, instead of exposing the standard
Enumerable
class, consider exposing your own extensions that are specifically designed for script code:
publicstaticclass ScriptWhere {
publicstatic IEnumerable<T> Where<T>(this IEnumerable<T> source, dynamic predicate) {
return source.Where(item => Convert.ToBoolean(predicate(item)));
}
}
Then you could do this:
engine.AddHostType("ScriptWhere", typeof(ScriptWhere));
engine.Execute(@"
result = uow.Projects.Where(function (w) { return w.Id == 100; }).ToList();
");
For
Select()
you can't get around having to specify the target type, but you could still make script code a bit happier:
publicstaticclass ScriptSelect {
publicstatic IEnumerable<T> Select<T>(this IEnumerable<object> source, dynamic selector) {
return source.Select(item => (T)selector(item));
}
}
And then:
engine.AddHostType("ScriptSelect", typeof(ScriptSelect));
engine.AddHostType("Int32", typeof(int));
engine.Execute(@"
result = uow.Projects.Select(Int32, function (w) { return w.Id; }).ToList();
");
We haven't explored all the possibilities; there are just a few ideas.
Good luck!