首页 新闻 赞助 找找看

.net 5 如何将字符串直接转换为 Linq?

0
悬赏园豆:5 [已解决问题] 解决于 2022-09-08 14:54

需求是,逻辑处理里有一坨结构化的数据,结构可能比较复杂,有各种属性,每种属性类型有简单类型(int, long, decimal 之类),也有自定义的类类型,也有List、Dictionary。并且这坨数据的结构是稳定的,在不同客户的应用和场景中,只会存在值不同,不会存在属性名字、类型的变化。

 

然后界面上提供一个输入框,在不同客户的应用和场景中,通过输入不同的表达式,得到客户所要求的数据或者数据集合。以免要给每个客户编译一个版本。

我使用 CSharpCompilation 进行动态编译,但是编译其它程序都没毛病,而在编译带 Linq 解析的字符串时,总是出错:

(12,17): error CS0012: 类型“Func<,>”在未引用的程序集中定义。必须添加对程序集“System.Runtime, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a”的引用。
(12,17): error CS0012: 类型“Func<,,>”在未引用的程序集中定义。必须添加对程序集“System.Runtime, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a”的引用。

 

以下是测试程序

 1 using Microsoft.CodeAnalysis;
 2 using Microsoft.CodeAnalysis.CSharp;
 3 using Microsoft.CodeAnalysis.Emit;
 4 using System;
 5 using System.Collections.Generic;
 6 using System.IO;
 7 using System.Linq;
 8 using System.Reflection;
 9 using System.Text;
10 using System.Threading.Tasks;
11 using System.Xml.Linq;
12 
13 namespace CSLanguageTest.Compile {
14     public class Test1 {
15         
16         private string GetCSLinqCode() {
17             StringBuilder sb = new StringBuilder();
18             sb
19                 .AppendLine("using System;")
20                 .AppendLine("using System.Collections.Generic;")
21                 .AppendLine("using CSLanguageTest.Compile;")
22                 .AppendLine("using System.Linq;")
23                 .AppendLine("using System.Runtime;")
24                 .AppendLine("using System.Xml.Linq;")
25                 .AppendLine("namespace Test {")
26                 .AppendLine("    public class Util {")
27                 .AppendLine("        public object GetQuery(List<Student> ds) {")
28                 .AppendLine("            var result = ")
29                 .AppendLine("                from stu in ds")
30                 .AppendLine("                where stu.Age > 28")
31                 .AppendLine("                select stu;")
32                 //.AppendLine("             return result;")
33                 .AppendLine("            return null;")
34                 .AppendLine("        }")
35                 .AppendLine("    }")
36                 .AppendLine("}")
37                 .AppendLine();
38             return sb.ToString();
39         }
40         
41 
42         public void F3() {
43             string csCode = this.GetCSLinqCode();
44 
45             SyntaxTree tree = CSharpSyntaxTree.ParseText(csCode);
46             var compilation =
47                 CSharpCompilation.Create("Test")
48                 .AddReferences(
49                     MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
50                     MetadataReference.CreateFromFile(typeof(List<Student>).Assembly.Location),
51                     MetadataReference.CreateFromFile(typeof(Student).Assembly.Location),
52                     MetadataReference.CreateFromFile(typeof(System.Runtime.GCSettings).Assembly.Location),
53                     MetadataReference.CreateFromFile(typeof(System.Runtime.CompilerServices.DynamicAttribute).Assembly.Location),
54                     MetadataReference.CreateFromFile(typeof(System.Linq.EnumerableQuery).Assembly.Location),
55                     MetadataReference.CreateFromFile(typeof(System.Xml.Linq.XCData).Assembly.Location)
56                     )
57                 .AddSyntaxTrees(tree)
58                 .WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
59 
60 
61             EmitResult emitResult;
62             byte[] dllBytes;
63             using (var stream = new MemoryStream()) {
64                 emitResult = compilation.Emit(stream);
65                 dllBytes = stream.ToArray();
66             }
67 
68             if (emitResult.Success) {
69                 Assembly assembly = Assembly.Load(dllBytes);
70                 var obj = assembly.CreateInstance("Test.Util");
71                 var method = obj.GetType().GetMethod("GetQuery", new Type[] { typeof(List<Student>) });
72                 Console.WriteLine(method);
73             } else {
74                 foreach(var error in emitResult.Diagnostics) {
75                     Console.WriteLine(error.ToString());
76                 }
77             }
78         }
79     }
80 }
using System;
using System.Collections.Generic;
using System.Linq;

namespace CSLanguageTest.Compile {
    public class Student {
        public string Name { get; set; }
        public int Age { get; set; }
    }
}
背锅狼的主页 背锅狼 | 初学一级 | 园豆:63
提问于:2022-09-05 09:02
< >
分享
最佳答案
0

建议试试 Microsoft.CodeAnalysis.CSharp.Scripting

var discountFilter = "album => album.Quantity > 0";
var options = ScriptOptions.Default.AddReferences(typeof(Album).Assembly);

Func<Album, bool> discountFilterExpression = await CSharpScript.EvaluateAsync<Func<Album, bool>>(discountFilter, options);

var discountedAlbums = albums.Where(discountFilterExpression);
//hooray now we have discountedAlbums!

详见 Easy way to create a C# lambda expression from a string (with Roslyn)

收获园豆:5
dudu | 高人七级 |园豆:31075 | 2022-09-05 09:17
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册