网站违规关键词,长沙房地产价格,怎么讲解网站,24小时有效地址域名基于 Roslyn 实现一个简单的条件解析引擎Intro最近在做一个勋章的服务#xff0c;我们想定义一些勋章的获取条件#xff0c;满足条件之后就给用户颁发一个勋章#xff0c;定义条件的时候会定义需要哪些参数#xff0c;参数的类型#xff0c;获取勋章的时候会提供所需要的参… 基于 Roslyn 实现一个简单的条件解析引擎Intro最近在做一个勋章的服务我们想定义一些勋章的获取条件满足条件之后就给用户颁发一个勋章定义条件的时候会定义需要哪些参数参数的类型获取勋章的时候会提供所需要的参数有一些内置的参数内置的参数解析器(ParamResolver)。最后基于 Roslyn 的 Script 动态编译功能实现了一个简单的条件解析引擎。Condition Eval Demo条件解析示例[Fact]
public async Task EvalTest()
{var condition xy 10;var variables JsonConvert.SerializeObject(new[]{new{Name x,Type int},new{Name y,Type int},});var params1 new Dictionarystring, 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(xx10);var variables JsonConvert.SerializeObject(new[]{new{Name list,Type Listint}});var params1 new{list new Listint(){1,2,3,4,5}};Assert.False(await ScriptEngine.EvalAsync(condition, variables, params1));var params2 new{list new Listint(){1,2,3,4,5,10,12}};Assert.True(await ScriptEngine.EvalAsync(condition, variables, params2));
}
实现原理实现的方式是基于 Roslyn 实现的核心实现是基于 Roslyn 的 Script 实现的但是 Roslyn Script 的执行有一些限制不支持匿名类对象的解析因此还基于 Roslyn 运行时根据变量信息来动态生成一个类型用于执行脚本解析var result await CSharpScript.EvaluateAsyncbool(1 2);
运行时动态生成代码在之前的 DbTool 项目中介绍过介绍文章 基于 Roslyn 实现动态编译详细实现细节可以参考代码 https://github.com/WeihanLi/SamplesInPractice/tree/master/ScriptEngineMemo程序集加载在 framework 和 core 环境下的差异实现的时候我们的项目有 dotnetcore 的还有 netframework 的这两者加载 dll 的时候略有不同实现的时候用了一个条件编译在 dotnet core 环境下和 dotnet framework 分开处理在 dotnetcore 中使用 AssemblyLoadContext 来加载程序集#if NETCOREAPPvar assembly AssemblyLoadContext.Default.LoadFromAssemblyPath(dllPath);
#elsevar assembly Assembly.LoadFile(dllPath);
#endif
程序集要保存到文件原本打算动态生成的程序集保存的一个 Stream 不保存文件但是实际测试下来必须要保存到文件才可以所以在项目根目录下创建了一个临时目录 temp 用来保存动态生成的程序集Roslyn 动态生成的程序集管理目前还是比较简单的放在一个 temp 目录下了总觉得每一个类型生成一个程序集有些浪费但是好像也没办法修改已有程序集还没找到比较好的解决方案如果有好的处理方式欢迎一起交流MoreNatasha 是一个基于 Roslyn 来实现动态编译能够让你更方便进行动态操作有动态编译相关需求的可以关注一下这个项目后面也想用 Natasha 来优化前面提到的问题基于roslyn的动态编译库为您提供高效率、高性能、可追踪的动态构建方案兼容stanadard2.0, 只需原生C#语法不用Emit。让您的动态方法更加容易编写、跟踪、维护Referencehttps://github.com/WeihanLi/SamplesInPractice/tree/master/ScriptEnginehttps://github.com/dotnet/roslyn/wiki/Scripting-API-Sampleshttps://github.com/dotnetcore/Natasha