c# 解释器模式与sping.net表达式的结合应用(金融里经常需要用到公式,这个公式是抽象的需要自己解释)
.代码
using Spring.Expressions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks; namespace ConsoleApplication49
{
public interface IExpressionContext
{
/// <summary>
/// 什么是终结符单词 客户端自己要给出
/// </summary>
Dictionary<string, string> map { get; set; }
string GetValueByKey(string key);
}
public class ExpressionContext : IExpressionContext
{
public Dictionary<string, string> map { get; set; }
public string GetValueByKey(string key)
{
if (map.ContainsKey(key))
return map[key];
return key;
}
}
public abstract class Expression
{
/// <summary>
/// 终结符
/// </summary>
private string key;
public string Key
{
get
{
return key;
} set
{
key = value;
}
} //解析公式和数值,其中var中的key值是是公式中的参数,value值是具体的数字
//这里字典可以抽象为上下文 ctx,此处自己扩展
public abstract string interpreter(IExpressionContext ctx); } public class VarExpression : Expression
{ public VarExpression(string _key)
{ this.Key = _key; } //从map中取之 public override string interpreter(IExpressionContext ctx)
{
if (ctx.map.ContainsKey(Key))
return ctx.GetValueByKey(Key);
else if (Key.IndexOf('(') >= )
{
var key1 = Key.Split('(')[];
return "(" + ctx.GetValueByKey(key1);
}
else if (Key.IndexOf(')') >= )
{
var key1 = Key.Split(')')[];
return ctx.GetValueByKey(key1) + ")";
}
return Key; } } public abstract class SymbolExpression : Expression
{ protected Expression left; protected Expression right; //所有的解析公式都应只关心自己左右两个表达式的结果 public SymbolExpression(Expression _left, Expression _right)
{ this.left = _left; this.right = _right; } } public class AddExpression : SymbolExpression
{ public AddExpression(Expression _left, Expression _right) : base(_left, _right)
{ } //把左右两个表达式运算的结果加起来 public override string interpreter(IExpressionContext ctx)
{ return (base.left.interpreter(ctx)) + "+" + (base.right.interpreter(ctx)); } }
public class SubExpression : SymbolExpression
{ public SubExpression(Expression _left, Expression _right) : base(_left, _right)
{ } //左右两个表达式相减 public override string interpreter(IExpressionContext ctx)
{ return base.left.interpreter(ctx) + "-" + base.right.interpreter(ctx); } }
public class MultExpression : SymbolExpression
{ public MultExpression(Expression _left, Expression _right) : base(_left, _right)
{ } //左右两个表达式相减 public override string interpreter(IExpressionContext ctx)
{ return base.left.interpreter(ctx) + "*" + base.right.interpreter(ctx); } }
public class Dividexpression : SymbolExpression
{ public Dividexpression(Expression _left, Expression _right) : base(_left, _right)
{ } //左右两个表达式相减 public override string interpreter(IExpressionContext ctx)
{ return base.left.interpreter(ctx) + "/" + base.right.interpreter(ctx); } }
public class PExpression : SymbolExpression
{ public PExpression(Expression _left, Expression _right) : base(_left, _right)
{ } //左右两个表达式相减 public override string interpreter(IExpressionContext ctx)
{ return base.left.interpreter(ctx) + "^" + base.right.interpreter(ctx); } } public class Calculator
{ //定义的表达式 private Expression expression; //构造函数传参,并解析 public Calculator(string exprStr)
{ //定义一个堆栈,安排运算的先后顺序 Stack<Expression> stack = new Stack<Expression>();
string[] sb = { "+", "-", "*", "/", "^" };
List<string> items = new List<string>();
string word = string.Empty;
char[] chs = exprStr.ToCharArray();
List<string> chsdict = new List<string>();
foreach (var item in chs)
{
chsdict.Add(item.ToString()); }
foreach (string ch in chsdict)
{ if (!sb.Contains(ch.ToString()))
{
word += ch.ToString();
//if (exprStr.IndexOf(ch) == exprStr.ToCharArray().Length - 1)
if (object.ReferenceEquals(ch, chsdict[chsdict.Count - ]))
{
items.Add(word);
}
}
else
{
items.Add(word.Clone().ToString());
items.Add(ch.ToString());
word = string.Empty;
} } int cx = ;
//表达式拆分为字符数组 char[] charArray = exprStr.ToCharArray(); //运算 Expression left = null; Expression right = null; for (int i = ; i < items.Count; i++)
{
if (cx >= items.Count)
{
break;
}
word = items[cx++]; switch (word)
{ case "+": //加法 //加法结果放到堆栈中 left = stack.Peek(); right = new VarExpression(items[cx++]); stack.Push(new AddExpression(left, right)); break; case "-": left = stack.Peek(); right = new VarExpression(items[cx++]); stack.Push(new SubExpression(left, right)); break;
case "^": left = stack.Peek(); right = new VarExpression(items[cx++]); stack.Push(new PExpression(left, right));
break;
case "/": left = stack.Peek(); right = new VarExpression(items[cx++]); stack.Push(new Dividexpression(left, right));
break;
case "*":
left = stack.Peek(); right = new VarExpression(items[cx++]); stack.Push(new MultExpression(left, right));
break;
default: //公式中的变量
stack.Push(new VarExpression(word));
break; } } //把运算结果抛出来 this.expression = stack.Peek(); } //开始运算 public string run(IExpressionContext ctx)
{ return this.expression.interpreter(ctx); } } public class Client
{ //运行四则运算 public static void Main(string[] args)
{
while (true)
{
string exp = string.Empty;
string expStr = getExpStr();
//赋值 得到终结符单词
Dictionary<string, string> maps = getValue(expStr);
Calculator cal = new Calculator(expStr);
IExpressionContext ctx = new ExpressionContext();
ctx.map = maps;
exp = cal.run(ctx);
var val = ExpressionEvaluator.GetValue(null, exp);
Console.WriteLine("运算结果为:" + expStr + "=" + exp + "=" + val.ToString());
}
Console.ReadKey(); } //获得表达式 public static String getExpStr()
{ Console.WriteLine("请输入表达式:"); return Console.ReadLine(); } //获得值映射 什么才是终结符单词客户端要自己给出定义 public static Dictionary<string, string> getValue(string exprStr)
{
exprStr = exprStr.Replace("(", "").Replace(")", ""); //定义非终结符
string[] sb = { "+", "-", "*", "/", "^" }; string copyExpStr = exprStr.Clone().ToString();
foreach (char ch in exprStr.ToCharArray())
{
if (sb.Contains(ch.ToString()))
{
copyExpStr = copyExpStr.Replace(ch.ToString(), ",");
} }
var items = copyExpStr.Split(','); Dictionary<string, string> map = new Dictionary<string, string>(); //解析有几个参数要传递 foreach (string ch in items)
{ if (!sb.Contains(ch.ToString()) && !Regex.IsMatch(ch, @"[0-9]+(.d+)?") && ch != "(" && ch != ")")
{ //解决重复参数的问题 if (!map.ContainsKey(ch.ToString()))
{
Console.WriteLine("请输入" + ch + "的值:"); string in1 = Console.ReadLine(); map.Add(ch.ToString(), in1); } } } return map; } }
}
2.客户端测试

c# 解释器模式与sping.net表达式的结合应用(金融里经常需要用到公式,这个公式是抽象的需要自己解释)的更多相关文章
- 解释器模式 Interpreter 行为型 设计模式(十九)
解释器模式(Interpreter) 考虑上图中计算器的例子 设计可以用于计算加减运算(简单起见,省略乘除),你会怎么做? 你可能会定义一个工具类,工具类中有N多静态方法 比如定义了两个 ...
- 设计模式 笔记 解释器模式 Interpreter
//---------------------------15/04/26---------------------------- //Interpreter 解释器模式----类行为型模式 /* 1 ...
- 设计模式之解释器模式(Interpreter)摘录
23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于怎样创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...
- Matlab解释器模式
解释器模式(Interperter),给定一个语言,定义一个语言的文法,并且建立一个解释器来解释该语言中的句子,实际开发中EL表达式或者正则表达式的解释器就是采用这种设计模式.其模式结构如下图.本文使 ...
- 设计模式(二十一)——解释器模式(Spring 框架中SpelExpressionParser源码分析)
1 四则运算问题 通过解释器模式来实现四则运算,如计算 a+b-c 的值,具体要求 1) 先输入表达式的形式,比如 a+b+c-d+e, 要求表达式的字母不能重复 2) 在分别输入 a ,b, c, ...
- interpreter(解释器模式)
一.引子 其实没有什么好的例子引入解释器模式,因为它描述了如何构成一个简单的语言解释器,主要应用在使用面向对象语言开发编译器中:在实际应用中,我们可能很少碰到去构造一个语言的文法的情况. 虽然你几乎用 ...
- [工作中的设计模式]解释器模式模式Interpreter
一.模式解析 解释器模式是类的行为模式.给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器.客户端可以使用这个解释器来解释这个语言中的句子. 以上是解释器模式的类图,事实上我 ...
- 解释器模式(Interpreter Pattern)
定义:给定一种语言,定义他的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中句子. 抽象解释器:声明一个所有具体表达式都要实现的抽象接口(或者抽象类),接口中主要是一个interpre ...
- C#设计模式——解释器模式(Interpreter Pattern)
一.概述 在软件开发特别是DSL开发中常常需要使用一些相对较复杂的业务语言,如果业务语言使用频率足够高,且使用普通的编程模式来实现会导致非常复杂的变化,那么就可以考虑使用解释器模式构建一个解释器对复杂 ...
随机推荐
- bzoj 4570: [Scoi2016]妖怪 凸包
题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=4570 题解 我们知道如果一个怪物要取到攻击力的最大值,那么一定是把防御力都转化了 所以我 ...
- prisma graphql 工具基本使用
项目使用docker-compose mysql 运行 安装 npm insatll -g prisma or yarn global add prisma 创建代码 项目结构 ├── README. ...
- Linux之 增加swap空间
引言 :有时候我们会遇到安装os时候,swap分区过小,导致某些大软件无法安装的问题.我们可以在linux下增大swap分区的空间. 以下的操作都要在root用户下执行: 0. 记录原 swap 分区 ...
- Dubbo 基础教程
原文地址:Dubbo 基础教程 博客地址:http://www.extlight.com 一.前言 当服务越来越多时,容量的评估,小服务资源的浪费等问题逐渐显现,此时需要增加一个调度中心基于访问压力实 ...
- vs2012,2013 update 离线下载(知识库)
由于微软提供的update是在线安装的. 加上layout参数可以全部下载完再安装. 命令行或批处理 VS2013.4.exe /layout
- linux svn soeasy
http://blog.163.com/longsu2010@yeah/blog/static/173612348201202114212933/
- vagrant 相关记录
最近安装vagrant 出错的最大的可能性是BOX 路径不太对, 好像和目录的大小写有关系,请检查 $ vagrant init # 初始化$ vagrant up # 启动虚拟机$ vagrant ...
- 关系型数据库与Key-value型数据库Mongodb模式设计对比
MongoDb 相比于传统的 SQL 关系型数据库,最大的不同在于它们的模式设计( Schema Design )上的差别,正是由于这一层次的差别衍生出其它各方面的不同. 我们可以简单的认为关系型数据 ...
- C++快速输出一个整数的二进制表示(不用写函数)
如果要输出int型的整数x,代码为: cout << bitset<>(x) << endl; 如果要输出long long型的整数x,代码为: cout < ...
- HDU-3944 DP?(组合数求模)
一.题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=3944 二.题意 给一个巨大的杨辉三角,采用类似DP入门题“数字三角形”的方式求从顶点$(0, 0) ...