c# 解释器模式与sping.net表达式的结合应用(金融里经常需要用到公式,这个公式是抽象的需要自己解释)

1.代码
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('(') >= 0)
            {
                var key1 = Key.Split('(')[1];
                return "(" + ctx.GetValueByKey(key1);
            }
            else if (Key.IndexOf(')') >= 0)
            {
                var key1 = Key.Split(')')[0];
                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 - 1]))
                    {
                        items.Add(word);
                    }
                }
                else
                {
                    items.Add(word.Clone().ToString());
                    items.Add(ch.ToString());
                    word = string.Empty;
                }


            }

            int cx = 0;
            //表达式拆分为字符数组

            char[] charArray = exprStr.ToCharArray();

            //运算

            Expression left = null;

            Expression right = null;

            for (int i = 0; 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.客户端测试

原文地址:https://www.cnblogs.com/kexb/p/6262132.html