需求

我们很难捉摸用户的思维,即使使用非常正式的文档规范某些数据的定义、结果的标准等,也不能抵挡住用户不断变化的需求,但他们有个万变不离的东西——你做这个东西要是万能的,即输入参数类型、个数等发生改变,也得生成出正确的结果。

在编程计算中,很多时候涉及一些公式,用户要求不但能够调整系数、还要能够调整理公式的结构。例如,将2+3-5调整理成2+3*5。我之前使用的解决方案是写一个类,换公式了,就继承它,写一个子类,代码中用反射去调用这个子类,可以解决问题。但是有些麻烦。

解决方案

现决定,用动态来解析公式的方法来解决这个问题。由于时间比较紧张,找到了一个开源的类库ExpressionEvaluator,没有深入研究,不过已经解决了我们的问题。

官网:http://csharpeval.codeplex.com/

使用示例

1.在官网下载ExpressionEvaluator. dll(2.0.4版),在网上搜索antlr3.runtime.dll(3.5.0.2版)

2.项目中引用这两个dll;

3.第一种情况,不需要变量,直接是常规的数字、符号、系统函数(Math类)的组合。

/// <summary>
/// 简单数值计算
/// </summary>
/// <param name="str">纯表达式</param>
/// <returns>返回值</returns>
public static string SimpleEval(string str)
{
var types = new TypeRegistry();
types.RegisterDefaultTypes(); var expression = new CompiledExpression(str) { TypeRegistry = types };
var result = expression.Eval();
Console.WriteLine("简单数值计算: {0}", result);
return result.ToString();
}

  

调用:

SimpleEval(this.textBox1.Text.Trim()

  

结果如下:

4.第二种情况,其中包含了一些变量(这种情况更多),需要将自己的变量写成一个类,然后注册这个类。

public class Result
{
public double Death { get; set; }
public double Injury { get; set; }
}

  

方法:

/// <summary>
/// 变量字段的计算
/// </summary>
/// <param name="str"></param>
/// <param name="type"></param>
/// <returns></returns>
public static string FieldEval(string str,Object type)
{
//注册
var reg = new TypeRegistry();
reg.RegisterSymbol("Result", type);
//如果要使用Math函数,还就注册这个
//reg.RegisterDefaultTypes(); //编译
var p = new CompiledExpression(str) { TypeRegistry = reg };
p.Compile(); //计算
Console.WriteLine("变量字段计算: {0}", p.Eval());
return p.Eval().ToString();
}

  

调用:

string[] strFields = new string[] { "Death","Injury"};
string exp = this.textBox2.Text.Trim();
for (int i = 0; i < strFields.Length;i++ )
{
if (exp.Contains(strFields[i]))
{
exp= exp.Replace(strFields[i], "Result." + strFields[i]);
} }
Result re = new Result()
{
Death = Convert.ToDouble(this.txtDeath.Text.Trim() + ""),
Injury = Convert.ToDouble(this.txtInjury.Text.Trim() + "")
}; ExpEvaluator.FieldEval(exp,re)

  

结果:

当然,还有其他内容需要研究、学习!

参考

Github地址:

https://github.com/RupertAvery/csharpeval

调用系统的Math函数:

http://csharpeval.codeplex.com/discussions/585878

C# 动态解析表达式的更多相关文章

  1. Java | 在 Java 中执行动态表达式语句: 前中后缀、Ognl、SpEL、Groovy、Jexl3

    在一些规则集或者工作流项目中,经常会遇到动态解析表达式并执行得出结果的功能. 规则引擎是一种嵌入在应用程序中的组件,它可以将业务规则从业务代码中剥离出来,使用预先定义好的语义规范来实现这些剥离出来的业 ...

  2. 表达式的动态解析和计算,Flee用起来真香

    前言 在很多项目中经常会出现需要动态解析表达式和计算的场景,比如一些自动审核规则,或者是一些变量的值通过维护的公式在运行过程中动态算出:由于场景需求,都需要比较灵活的配置对应的表达式,然后希望在需要的 ...

  3. 集算器协助java处理多样性数据源之MongoDB

    MongoDB不支持join,其官网上推荐的unity jdbc可以把数据取出来进行二次计算实现join运算,但这些join.group.函数.表达式等高级功能都是收费版才有,而且即使是收费版本,对子 ...

  4. 集大软件工程15级结对编程week1

    集大软件工程15级结对编程week1 0. 团队成员 姓名 学号 博客园首页 码云主页 孙志威 20152112307 Agt Eurekaaa 孙慧君 201521123098 野原泽君 野原泽君 ...

  5. JAVA反射会降低你的程序性能吗?

    原文出处 早两天写了<从把三千行代码重构成15行代码谈起>这篇文章,看到评论中有一些同学的回复还是在质疑反射的性能,好像程序用上了反射,就像开上了拖拉机似的.本来我觉得这个话题没有什么好讨 ...

  6. Code Project精彩系列(转)

    Code Project精彩系列(转)   Code Project精彩系列(转)   Applications Crafting a C# forms Editor From scratch htt ...

  7. MongoDB里做表间关联

    MongoDB与关系型数据库的建模还是有许多不同,因为MongoDB支持内嵌对象和数组类型.MongoDB建模有两种方式,一种是内嵌(Embed),另一种是连接(Link).那么何时Embed何时Li ...

  8. 关于模板中的动态取值 ---反射与javascript脚本编译

    在项目中经常遇到一个问题,打印word或者打印excel的时候,我们经常使用一对一的赋值或者批量替换的方式来对模板进行修改. 但是现在遇到两种场景: 1.取值是通过自定以方法进行取值的. 如:一个销售 ...

  9. C#中的动态特性

    众所周知,C#和Java一样,都是一门静态语言.在C# 4.0之前,想要和动态语言(诸如Python.Javascript等)进行方便地互操作是一件不太容易的事情.而C# 4.0为我们带来的dynam ...

随机推荐

  1. Android 实现页面跳转并传递参数教程

    首先我们来看一下实现的功能:     第二,我们看一下实现这个功能,总共会接触到哪些文件和代码. 1.实现本功能总共涉及如下6个文件 2.实现本功能,总共涉及如下6个文件中的如下代码: (1) 效果: ...

  2. Linux的命名空间详解--Linux进程的管理与调度(二)

    转自:http://blog.csdn.net/gatieme/article/details/51383322 日期 内核版本 架构 作者 GitHub CSDN 2016-05-12 Linux- ...

  3. jquery插件--在input下输入密码时提示大写锁定键

    //密码大写输入提示 function capitalTip(id){ $('#' + id).after('<div class="capslock" id="c ...

  4. PlaceholderTextView

    PlaceholderTextView 效果 源码 https://github.com/YouXianMing/UI-Component-Collection 的 PlaceholderTextVi ...

  5. java数组和字符串相互转换

    将字符串变成数组 Java.lang包中有String.split()方法,java中通常用split()分割字符串,返回的是一个数组. 特殊,转义字符,必须加"\\"(“.”和“ ...

  6. 生成模型(Generative Model)和 判别模型(Discriminative Model)

    引入 监督学习的任务就是学习一个模型(或者得到一个目标函数),应用这一模型,对给定的输入预测相应的输出.这一模型的一般形式为一个决策函数Y=f(X),或者条件概率分布P(Y|X). 监督学习方法又可以 ...

  7. asp.net mvc Controller控制器返回类型

    ASP.NET MVC包括了执行常见任务的ActionResult类型.这些类型罗列在表5-1中.每个类型都将在随后的小节中详细讨论. 表5-1  动作结果的类型及其说明 动作结果的类型 说    明 ...

  8. go语言之进阶篇主协程先退出

    1.主协程先退出 示例: package main import ( "fmt" "time" ) //主协程退出了,其它子协程也要跟着退出 func main ...

  9. iOS开发--知识点总结

    1 .全局变量,变量名前加下划线.和系统一致. 2 . nil指针为空   @“”字符串为空 (内容为空)       ==  判断内存地址   基本变量    对于一些基本类型 可以使用==来判断, ...

  10. 在OneNote中快速插入当前日期和时间

    做笔记,难免有时需要记录当时的时间,记住这个快捷键会让记笔记的效率提升一点. To insert the current date and time, press Alt+Shift+F. To in ...