使用CodeAnalysis编译C#脚本失败:缺少哪个程序集?
问题
编译执行C#脚本时出现以下错误:
- CS0103: 名称“Queryable”在当前上下文中不存在
- CS1061: “int[]”不包含“AsQueryable”的定义,也找不到可接受第一个参数类型为“int[]”的可访问扩展方法“AsQueryable”(是否缺少using指令或程序集引用?)
已在refPaths中通过typeof(Enumerable).GetTypeInfo().Assembly.Location添加了System.Linq相关引用,但仍报错,询问缺少的程序集。
相关代码如下:
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); } } } }
解决方案
你缺少的是包含System.Linq.Queryable类型的程序集引用。Queryable类以及AsQueryable扩展方法均定义在该程序集中——虽然Enumerable和Queryable同属System.Linq命名空间,但在部分.NET版本中二者分属不同程序集,即便在.NET Core/.NET 5+环境下,也需显式引用包含Queryable的程序集。
只需在refPaths数组中添加以下条目即可解决:
typeof(System.Linq.Queryable).GetTypeInfo().Assembly.Location
修改后的refPaths示例:
var refPaths = new[] { typeof(object).GetTypeInfo().Assembly.Location, typeof(Console).GetTypeInfo().Assembly.Location, typeof(Enumerable).GetTypeInfo().Assembly.Location, typeof(System.Linq.Queryable).GetTypeInfo().Assembly.Location, // 新增引用Queryable所在程序集 Path.Combine(Path.GetDirectoryName (typeof(System.Runtime.GCSettings). GetTypeInfo().Assembly.Location), "System.Runtime.dll"), };
内容的提问来源于stack exchange,提问作者lucidgold
相关产品推荐
相关产品推荐

