天天看點

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.用戶端測試
      
c# 解釋器模式與sping.net表達式的結合應用(金融裡經常需要用到公式,這個公式是抽象的需要自己解釋)...

轉載于:https://www.cnblogs.com/kexb/p/6262132.html