Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# scripting API does not load assembly

Tags:

c#

scripting

I tried to write a .net core console program to use the C# scripting API to run a linq statement, but I keep getting error saying

'System.Linq, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' ---> System.IO.FileLoadException: Native image cannot be loaded multiple times.

Here is my program:

using System;
using System.Collections.Generic;
using System.Reflection;
using Microsoft.CodeAnalysis.CSharp.Scripting;
using Microsoft.CodeAnalysis.Scripting;

namespace ConsoleApplication
{
    public class Program
    {
        public static void Main(string[] args)
        {
            try
            {
                var scriptOptions = ScriptOptions.Default;

                //Add reference to mscorlib
                var mscorlib = typeof(System.Object).GetTypeInfo().Assembly;
                var systemCore = typeof(System.Linq.Enumerable).GetTypeInfo().Assembly;
                scriptOptions = scriptOptions.AddReferences(mscorlib, systemCore);

                //Add namespaces
                scriptOptions = scriptOptions.AddImports("System");
                scriptOptions = scriptOptions.AddImports("System.Linq");
                scriptOptions = scriptOptions.AddImports("System.Collections.Generic");

                var state = CSharpScript.RunAsync(@"var x = new List<int>(){1,2,3,4,5};", scriptOptions).Result;
                state = state.ContinueWithAsync("var y = x.Take(3).ToList();").Result;

                var y = state.Variables[1];
                var yList = (List<int>)y.Value;
                foreach(var val in yList)
                {
                Console.Write(val + " "); // Prints 1 2 3
                }
            }
            catch (CompilationErrorException e)
            {
                Console.WriteLine(string.Join(Environment.NewLine, e.Diagnostics));
            }
            catch (Exception e)
            {
                Console.WriteLine(string.Join(Environment.NewLine, e));
            }
        }
    }
}

Here is my project.json:

{
  "version": "1.0.0-*",
  "buildOptions": {
    "debugType": "portable",
    "emitEntryPoint": true
  },
  "dependencies": {
    "Microsoft.CodeAnalysis.CSharp.Scripting": "2.0.0-rc2"
  },
  "frameworks": {
    "netcoreapp1.1": {
      "dependencies": {
        "Microsoft.NETCore.App": {
          "type": "platform",
          "version": "1.1.0"
        }
      },
      "imports": ["dnxcore50", "net452"]
    }
  }
}
like image 835
Ethan Li Avatar asked Dec 11 '22 13:12

Ethan Li


1 Answers

Seems to be a dependency conflict between Microsoft.CodeAnalysis.Scripting and Microsoft.NETCore.App targeting different versions of the System dlls, until those are aligned, it looks like you can use the InteractiveAssemblyLoader to tell the CSharpScript compiler to load the version of the dependencies that the app actually provides.

    var scriptOptions = ScriptOptions.Default;

    // Add reference to mscorlib
    var mscorlib = typeof(object).GetTypeInfo().Assembly;
    var systemCore = typeof(System.Linq.Enumerable).GetTypeInfo().Assembly;

    var references = new[] { mscorlib, systemCore };
    scriptOptions = scriptOptions.AddReferences(references);

    List<int> yList;
    using (var interactiveLoader = new InteractiveAssemblyLoader())
    {
        foreach (var reference in references)
        {
            interactiveLoader.RegisterDependency(reference);
        }

        // Add namespaces
        scriptOptions = scriptOptions.AddImports("System");
        scriptOptions = scriptOptions.AddImports("System.Linq");
        scriptOptions = scriptOptions.AddImports("System.Collections.Generic");

        // Initialize script with custom interactive assembly loader
        var script = CSharpScript.Create(@"", scriptOptions, null, interactiveLoader);
        var state = script.RunAsync().Result;

        state = state.ContinueWithAsync(@"var x = new List<int>(){1,2,3,4,5};").Result;
        state = state.ContinueWithAsync("var y = x.Take(3).ToList();").Result;

        var y = state.Variables[1];
        yList = (List<int>)y.Value;
    }

    foreach (var val in yList)
    {
        Console.Write(val + " "); // Prints 1 2 3
    }

    // ...
like image 127
Joshua Webb Avatar answered Dec 13 '22 03:12

Joshua Webb