Evaluate and run a script with Blazor WASM

Viewed 319

I have a code that works as expected on the server that generates C# code dynamically and then runs it. To run the code I use the following:

string assemblyPath = Path.GetDirectoryName(typeof(object).Assembly.Location);
MetadataReference[] references = new MetadataReference[]
{
    MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
    MetadataReference.CreateFromFile(typeof(Enumerable).Assembly.Location),
    MetadataReference.CreateFromFile(typeof(RunResult).Assembly.Location),
    MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.Console.dll")),
    MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.Runtime.dll")),
    MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.Runtime.Extensions.dll")),
    MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.Collections.dll")),
    MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.Text.Json.dll"))
};

var f =
    await CSharpScript.Create(
            code: code,
            options: ScriptOptions.Default.WithReferences(references))
        .ContinueWith<Func<RunResult, bool>>("new EvaluatorClass().Run")
        .CreateDelegate()
        .Invoke();

await using (MemoryStream ms = new MemoryStream())
{
    await using (StreamWriter currentOut = new StreamWriter(ms) { AutoFlush = true })
    {
        var runResult = f(codeResult);
    }
}

I have written this code as part of a .NET Standard library, and I would now like to run this on the client side using Blazor WebAssembly.

When I debugged I saw that the problem is that string assemblyPath = Path.GetDirectoryName(typeof(object).Assembly.Location); returns null, and therefor it's not possible (as far as I know) to include the references that are needed by the code being executed.

Is there another way this could be achieved so it would work on Blazor?

1 Answers

could you try inferring references, instead of loading files?

var scriptOptions = ScriptOptions.Default;
scriptOptions = scriptOptions.AddReferences(
    typeof(System.Object).GetTypeInfo().Assembly,
    typeof(System.Linq.Enumerable).GetTypeInfo().Assembly,
    /* don't know where `RunResult` comes from, add it yourself */);
scriptOptions = scriptOptions.AddImports(
    "System.Console",
    "System.Runtime",
    "System.Runtime.Extensions",
    "System.Collections",
    "System.Text.Json");

var f =
    await CSharpScript.Create(
            code: code,
            options: scriptOptions)
        [...etc...]

edit: i've edited in the scriptOptions = scriptOptions.[...] notation. I don't get it, but it seems to be the way people do it online... It seems wrong to me. edit2: Ok, found it ScriptOption seems to use immutable data structures internally. So the calls will (likely) return a new object.

Related