mardi 7 février 2023

Cannot Compile C# Script via CodeAnalysis: Which assembly am I missing?

The following program attempts to compile and execute a script of C#. However, I keep getting the output:

CS0103: The name 'Queryable' does not exist in the current context

CS1061: 'int[]' does not contain a definition for 'AsQueryable' and no accessible extension method 'AsQueryable' accepting a first argument of type 'int[]' could be found (are you missing a using directive or an assembly reference?)

Which assembly am I missing in refPaths? I assumed [System.Linq] would be all I need, which I then added through [typeof(Enumerable).GetTypeInfo().Assembly.Location].

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Emit;

namespace CompileScript
{
    class Program
    {
        static async Task Main(string[] args)
        {
            string script = @"using System;
                              using System.Linq;

                              namespace Test { class Program {
                              public static void Main() {
                                   Console.WriteLine(""Testing a script..."");
                                   int[] arr = new int[] { 1, 2, 3};
                                   double avg = Queryable.Average(arr.AsQueryable());
                                   Console.WriteLine(""Average = "" + avg);}}}";

             var refPaths = new[] {
                   typeof(object).GetTypeInfo().Assembly.Location,
                   typeof(Console).GetTypeInfo().Assembly.Location,
                   typeof(Enumerable).GetTypeInfo().Assembly.Location,
                   Path.Combine(Path.GetDirectoryName
                   (typeof(System.Runtime.GCSettings).
                   GetTypeInfo().Assembly.Location), "System.Runtime.dll"),
             };
             SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(script);

             string assemblyName = Path.GetRandomFileName();

             MetadataReference[] references = refPaths.Select(r => MetadataReference.
             CreateFromFile(r)).ToArray();

             CSharpCompilation compilation = CSharpCompilation.Create(
                  assemblyName,
                  syntaxTrees: new[] { syntaxTree },
                  references: references,
                  options: new CSharpCompilationOptions
                  (OutputKind.DynamicallyLinkedLibrary));

            using var ms = new MemoryStream();
            EmitResult result = compilation.Emit(ms);

            if (!result.Success)
            {
                   IEnumerable<Diagnostic> failures =
                        result.Diagnostics.Where(diagnostic =>
                        diagnostic.IsWarningAsError ||
                        diagnostic.Severity == DiagnosticSeverity.Error);

                   foreach (Diagnostic diagnostic in failures)
                   {
                      Console.WriteLine("\t{0}: {1}", diagnostic.Id,
                                                      diagnostic.GetMessage());
                   }
             }
             else
             {
                  ms.Seek(0, SeekOrigin.Begin);

                  Assembly assembly = AssemblyLoadContext.Default.LoadFromStream(ms);
                  var type = assembly.GetType("Test.Program");
                  var instance = assembly.CreateInstance("Test.Program");
                  MethodInfo? methodInfo = type.GetMethod("Main");
                  methodInfo.Invoke(instance, null);
              }
          }
       }
   }




Aucun commentaire:

Enregistrer un commentaire