EvaluateExpression doesn't seem to like List<string> or Linq methods

I have a window with a TextBox (expr) and a TextBlock (output).

When I add StringList class as global script item, evaluateexpression always returns null, even if the StringList isn’t referenced in the expression, eg. 2+2.
Also it seems like EvaluateExpression doesn’t understand Linq, eg:
_data.Items.Where(i => i.Name == “B”).First().Name

Is this correct or am I doing something wrong?
Are there any sort of documentation of what EvaluateExpression understands?

Code example:
public partial class MainWindow : Window
{
private DataClass _data = new DataClass();
private ScriptRun _scriptRun = new ScriptRun();
private StringList _strings = new StringList();

    public MainWindow()
    {
        InitializeComponent();

        _scriptRun.ScriptSource.WithDefaultReferences();
        _scriptRun.AssemblyKind = ScriptAssemblyKind.DynamicLibrary;
        _scriptRun.ScriptSource.References.Add("PresentationCore");
        _scriptRun.ScriptSource.References.Add("WindowsBase");

        _strings.Add("a");
        _strings.Add("b");
        _strings.Add("c");

        var sgi = new ScriptGlobalItem("_data", typeof(DataClass), _data);
        _scriptRun.GlobalItems.Add(sgi);

        //EvaluateExpression always returns null (even 2+2) when this ScriptGlobalItem is added
        sgi = new ScriptGlobalItem("_strings", typeof(StringList), _strings); 
        _scriptRun.GlobalItems.Add(sgi);
    }

    private void expr_KeyDown(object sender, KeyEventArgs e)
    {
        switch (e.Key)
        {
            case Key.Enter:
                var res = _scriptRun.EvaluateExpression(this.expr.Text);
                this.output.Text = res?.ToString() ?? "null";
                
                break;
            default: 
                break;
        }
    }
}

class StringList : List<string>
{
    public string GetString(int i) => this[i];
}

public class DataItem
{
    public string Name { get; set; }
}

public class DataClass
{
    public List<DataItem> Items { get; set; } = new List<DataItem>();
    public string Name { get; set; } = "Jazz";
    public string Description { get; set; } = "funk";
    public int Value { get; set; } = 5;
    public int GetValue(int i) => Value * i;

    public DataClass()
    {
        Items.Add(new() { Name = "A" });
        Items.Add(new() { Name = "B" });
        Items.Add(new() { Name = "C" });
    }
}

Hello,

For that to work, you would need to change two things:

  1. Add the following line:
    _scriptRun.ScriptSource.Imports.Add(“System.Linq”);

  2. Change visibility of StringList to public.

Also it is helpful to output the compiler errors before trying to evaluate expression with a code like this:

_scriptRun.ScriptSource.FromExpression(this.expr.Text);
if (!_scriptRun.Compile())
{
    MessageBox.Show(string.Join("\n", _scriptRun.ScriptHost.CompilerErrors.Select(x => x.ToString())));
    return;
}

Please try the modified code:

public partial class MainWindow : Window
{
    private DataClass _data = new DataClass();
    private ScriptRun _scriptRun = new ScriptRun();
    private StringList _strings = new StringList();

    public MainWindow()
    {
        InitializeComponent();

        _scriptRun.ScriptSource.WithDefaultReferences();
        _scriptRun.AssemblyKind = ScriptAssemblyKind.DynamicLibrary;
        _scriptRun.ScriptSource.References.Add("PresentationCore");
        _scriptRun.ScriptSource.References.Add("WindowsBase");

        _scriptRun.ScriptSource.Imports.Add("System.Linq");

        _strings.Add("a");
        _strings.Add("b");
        _strings.Add("c");

        var sgi = new ScriptGlobalItem("_data", typeof(DataClass), _data);
        _scriptRun.GlobalItems.Add(sgi);

        expr.Text = "_data.Items.Where(i => i.Name == \"B\").First().Name";

        sgi = new ScriptGlobalItem("_strings", typeof(StringList), _strings);
        _scriptRun.GlobalItems.Add(sgi);
    }

    private void expr_KeyDown(object sender, KeyEventArgs e)
    {
        switch (e.Key)
        {
            case Key.Enter:
                _scriptRun.ScriptSource.FromExpression(this.expr.Text);
                if (!_scriptRun.Compile())
                {
                    MessageBox.Show(string.Join("\n", _scriptRun.ScriptHost.CompilerErrors.Select(x => x.ToString())));
                    return;
                }

                var res = _scriptRun.EvaluateExpression(this.expr.Text);
                this.output.Text = res?.ToString() ?? "null";

                break;
            default:
                break;
        }
    }
}

public class StringList : List<string>
{
    public string GetString(int i) => this[i];
}

public class DataItem
{
    public string Name { get; set; }
}

public class DataClass
{
    public List<DataItem> Items { get; set; } = new List<DataItem>();
    public string Name { get; set; } = "Jazz";
    public string Description { get; set; } = "funk";
    public int Value { get; set; } = 5;
    public int GetValue(int i) => Value * i;

    public DataClass()
    {
        Items.Add(new() { Name = "A" });
        Items.Add(new() { Name = "B" });
        Items.Add(new() { Name = "C" });
    }
}

Let me know if it helps.

Thanks for the response.
I discovered the ScriptError event during the weekend, which clarified both issues for me. Everything works beautifully now :slight_smile: