在C#中解决动态计算表达式的问题(如字符串"Sin(1)+Cos(2)",执行并得出结果)

来源:互联网 发布:javascript对象构造器 编辑:程序博客网 时间:2024/05/29 02:24

前一阵公司老总要求我去重构一个同事的程序,里面有各种计算公式,如下图


这个公式的算法是这样 

0.058419 + 0.084612 * (log10(第二个文本框的值 / 第一个文本框的值)) + 0.3464 * 第三个文本框的值 + 0.00387 * 第四个文本框的值

另一个公式如下图


公式是这样

0.135 + 0.165 * log10(第一个文本框的值/第二个文本框的值)

这两个公式用的是同一窗体,只是加载窗体的时候使用不同的公式而已,所以界面显示的文本框数量,和一些说明文字不一样.

每个公式需要的参数个数不一同,公式算法不一样

我脑海里第一个闪现的做法就是把这些信息整合进一个XML里面进行配置,把计算的公式放进XML里面,呵呵,但是这样仍然解决不了我的问题

现在的公式成了字符串了,而不是程序里面的变量.

由此我想到几种解决方案,它们都属于动态编译,我找到一本英文资料,专门讲C#的元编程<<Manning Metaprogramming in NET 2013>>

这本书提到几种动态编译的方法

1.CodeDom 

2.Refection.Emit

3.Lambda表达式树

4.DLR 

4个我都看了一下,做了以下总结跟实践

方法1非常好,可以动态编译C#的代码,比如在一个文件框里写MessageBox.Show(......)然后读取文本框里的代码执行,就可以弹出一个文本框,如下图

Sample Image - EvalCSCode.jpg

.Net Expression Evaluator using DynamicMethod

 由此我找到两个来自CodeProject的程序

       http://www.codeproject.com/Articles/11939/Evaluate-C-Code-Eval-Function

       http://www.codeproject.com/Articles/18004/Net-Expression-Evaluator-using-DynamicMethod

这两个例子都非常好,尤其是第一个例子,演示了怎么执行一段字符串写的代码,以及外部的代码怎么跟字符串写的代码交互,但是要完成我的需要,要写的代码不少!

方法2是操作IL中间语言,我看了一下它的生成代码方式,有一定的灵活度,但要达到我这个程序的要求是太难,太烦,太麻烦!

方法3其生成代码的过程跟方法2比较像,但要轻量级一些,没那么繁琐,它主要是为了动态的生成一个Lambda表达式,但跟方法2一样,不太方便

方法4DLR与动态语言交互,目前.net已经很好的支持了两种脚本语言,Python和Ruby!看了一下Python的语法,感觉比较"轻便"!于是我把公式的计算翻译成Python代码并放入XML文件中,如下

  <FormulaInfo MethodSmartPart = "EmpiricalCyq" FormulaName="陈元千相关经验公式"     ParameterNameGroup = "地层原油粘度μo(mPa.s)|平均空气渗透率K(mD)|有效孔隙度φ(f)|井网密度S(口/km²)"     ParameterRange = "0.5-154.0|4.8-8900.0|0.15-0.33|3.1-28.3"     ValidParameter = "0.5-154.0|4.8-8900.0|0.15-0.33|3.1-28.3"     Image = "陈元千相关经验公式"     Code="def cal(): return 0.058419 + 0.084612 * (log10(float(ArrayCan[1].Text) / float(ArrayCan[0].Text))) + 0.3464 * float(ArrayCan[2].Text) + 0.00387 * float(ArrayCan[3].Text)" />
具体做法,我在我的另一篇文章里面有

http://blog.csdn.net/lee576/article/details/18734253

关于IronPython的资料还有一篇写的比较好:

C# 4.0 动态调用 IronPython

http://blog.csdn.net/goldworm2012/article/details/7621632

这个工作做完以后,我感觉方法1还是不错的,但是跟方法4相比,它稍微"重"了一点,但是在执行其它任务时,它是最好的(比如执行一段由字符串写的代码),方法4用来做动态解析计算的时候最合适,代码量少,清晰,并且Python在做科学计算方面比C#要强

2 0
原创粉丝点击