日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

基于 Roslyn 实现一个简单的条件解析引擎

發(fā)布時(shí)間:2023/12/4 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于 Roslyn 实现一个简单的条件解析引擎 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

基于 Roslyn 實(shí)現(xiàn)一個(gè)簡(jiǎn)單的條件解析引擎

Intro

最近在做一個(gè)勛章的服務(wù),我們想定義一些勛章的獲取條件,滿(mǎn)足條件之后就給用戶(hù)頒發(fā)一個(gè)勛章,定義條件的時(shí)候會(huì)定義需要哪些參數(shù),參數(shù)的類(lèi)型,獲取勛章的時(shí)候會(huì)提供所需要的參數(shù),有一些內(nèi)置的參數(shù),內(nèi)置的參數(shù)解析器(ParamResolver)。

最后基于 Roslyn 的 Script + 動(dòng)態(tài)編譯功能實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的條件解析引擎。

Condition Eval Demo

條件解析示例:

[Fact] public async Task EvalTest() {var condition = "x+y > 10";var variables = JsonConvert.SerializeObject(new[]{new{Name = "x",Type = "int"},new{Name = "y",Type = "int"},});var params1 = new Dictionary<string, object>(){{ "x", 2 },{ "y", 3 }};Assert.False(await ScriptEngine.EvalAsync(condition, variables, params1));var params1_1 = JsonConvert.SerializeObject(params1);Assert.False(await ScriptEngine.EvalAsync(condition, variables, params1_1));var params2 = new{x = 6,y = 5};Assert.True(await ScriptEngine.EvalAsync(condition, variables, params2)); } [Fact] public async Task EvalStringTest() {var condition = "x > y.Length";var variables = JsonConvert.SerializeObject(new[]{new{Name = "x",Type = "int"},new{Name = "y",Type = "string"},});var params1 = new{x = 1,y = "3"};Assert.False(await ScriptEngine.EvalAsync(condition, variables, params1));var params2 = new{x = 6,y = "5211"};Assert.True(await ScriptEngine.EvalAsync(condition, variables, params2)); } [Fact] public async Task EvalLinqTest() {var condition = "list.Any(x=>x>10)";var variables = JsonConvert.SerializeObject(new[]{new{Name = "list",Type = "List<int>"}});var params1 = new{list = new List<int>(){1,2,3,4,5}};Assert.False(await ScriptEngine.EvalAsync(condition, variables, params1));var params2 = new{list = new List<int>(){1,2,3,4,5,10,12}};Assert.True(await ScriptEngine.EvalAsync(condition, variables, params2)); }

實(shí)現(xiàn)原理

實(shí)現(xiàn)的方式是基于 Roslyn 實(shí)現(xiàn)的,核心實(shí)現(xiàn)是基于 Roslyn 的 Script 實(shí)現(xiàn)的,但是 Roslyn Script 的執(zhí)行有一些限制,不支持匿名類(lèi)對(duì)象的解析,因此還基于 Roslyn 運(yùn)行時(shí)根據(jù)變量信息來(lái)動(dòng)態(tài)生成一個(gè)類(lèi)型用于執(zhí)行腳本解析

var result = await CSharpScript.EvaluateAsync<bool>("1 > 2");

運(yùn)行時(shí)動(dòng)態(tài)生成代碼在之前的 DbTool 項(xiàng)目中介紹過(guò),介紹文章 基于 Roslyn 實(shí)現(xiàn)動(dòng)態(tài)編譯

詳細(xì)實(shí)現(xiàn)細(xì)節(jié)可以參考代碼 https://github.com/WeihanLi/SamplesInPractice/tree/master/ScriptEngine

Memo

程序集加載在 framework 和 core 環(huán)境下的差異

實(shí)現(xiàn)的時(shí)候我們的項(xiàng)目有 dotnetcore 的,還有 netframework 的,這兩者加載 dll 的時(shí)候略有不同,實(shí)現(xiàn)的時(shí)候用了一個(gè)條件編譯,在 dotnet core 環(huán)境下和 dotnet framework 分開(kāi)處理,在 dotnetcore 中使用 AssemblyLoadContext 來(lái)加載程序集

#if NETCOREAPPvar assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(dllPath); #elsevar assembly = Assembly.LoadFile(dllPath); #endif

程序集要保存到文件

原本打算動(dòng)態(tài)生成的程序集保存的一個(gè) Stream 不保存文件,但是實(shí)際測(cè)試下來(lái)必須要保存到文件才可以,所以在項(xiàng)目根目錄下創(chuàng)建了一個(gè)臨時(shí)目錄 temp 用來(lái)保存動(dòng)態(tài)生成的程序集

Roslyn 動(dòng)態(tài)生成的程序集管理

目前還是比較簡(jiǎn)單的放在一個(gè) temp 目錄下了,總覺(jué)得每一個(gè)類(lèi)型生成一個(gè)程序集有些浪費(fèi),但是好像也沒(méi)辦法修改已有程序集,還沒(méi)找到比較好的解決方案,如果有好的處理方式,歡迎一起交流

More

Natasha 是一個(gè)基于 Roslyn 來(lái)實(shí)現(xiàn)動(dòng)態(tài)編譯,能夠讓你更方便進(jìn)行動(dòng)態(tài)操作,有動(dòng)態(tài)編譯相關(guān)需求的可以關(guān)注一下這個(gè)項(xiàng)目,后面也想用 Natasha 來(lái)優(yōu)化前面提到的問(wèn)題

基于roslyn的動(dòng)態(tài)編譯庫(kù),為您提供高效率、高性能、可追蹤的動(dòng)態(tài)構(gòu)建方案,兼容stanadard2.0, 只需原生C#語(yǔ)法不用Emit。讓您的動(dòng)態(tài)方法更加容易編寫(xiě)、跟蹤、維護(hù)

Reference

  • https://github.com/WeihanLi/SamplesInPractice/tree/master/ScriptEngine

  • https://github.com/dotnet/roslyn/wiki/Scripting-API-Samples

  • https://github.com/dotnetcore/Natasha

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的基于 Roslyn 实现一个简单的条件解析引擎的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。