Dynamic Expresso 試用紀錄

dynamic expression, 動態運算式, 動態表達式,

引言

偶而會有動態表達式的需求。

關鍵知識

發現一個不錯的方案:Dynamic Expresso。支授二種使用方式:

一、Eval, 每次都重新解析運算式並執行。若跑重複的運算式就較慢。

二、Parse & Invok, 解析運算式拿到 lambda;之後再執行此 lambda。這樣跑重複的運算就較快。

參數代入有二種方法

一、Varialbe, 為 Interpreter 的共享變數;可讓之下全部的 expression 共用。

二、Parameter, 只針對每個 expression 有效。

試用紀錄

Eval

@using DynamicExpresso

<MudPaper role="panel">
  <MudText Typo=Typo.h6>Eval</MudText>
  <MudNumericField T="decimal" Label="foo" @bind-Value=foo />
  <MudNumericField T="decimal" Label="bar" @bind-Value=bar />
  <MudTextField Label="expression" @bind-Value=expression />
  <MudButton Variant=Variant.Filled Color=Color.Primary OnClick=HandleEval>Eval</MudButton>
  <MudText>message: @message</MudText>
</MudPaper>

@code {
  string message = string.Empty;
  decimal foo = 987654321m;
  decimal bar = 7654321m;
  string expression = "foo - bar";

  async Task HandleEval()
  {
    try
    {
      message = "計算中...";
      await Task.Yield();

      //------ 關鍵程式碼 eval & apply
      var result = new Interpreter().Eval(expression,
         new Parameter("foo", foo),
         new Parameter("bar", bar));

      message = $"{result}";
    }
    catch (Exception ex)
    {
      message = $"出現例外: " + ex.GetType().Name + ", " + ex.Message;
    }
  }
}

Parse & Invoke

@using DynamicExpresso

<MudPaper role="panel">
  <MudText Typo=Typo.h6>Parse & Invoke</MudText>
  <MudNumericField T="decimal" Label="foo" @bind-Value=foo />
  <MudNumericField T="decimal" Label="bar" @bind-Value=bar />
  <MudTextField Label="expression" @bind-Value=expression />
  <MudButton Variant=Variant.Filled Color=Color.Primary OnClick=HandleParse>Parse</MudButton>
  <MudButton Variant=Variant.Filled Color=Color.Primary OnClick=HandleInvoke>Invoke</MudButton>
  <MudText>message: @message</MudText>
</MudPaper>

@code {
  string message = string.Empty;
  decimal foo = 987654321m;
  decimal bar = 7654321m;
  string expression = "foo - bar";

  Lambda? lambda = null;

  async Task HandleParse()
  {
    try
    {
      message = "解析中...";
      await Task.Yield();

      var interpreter = new Interpreter();
      //interpreter.SetVariable("foo", foo);
      //interpreter.SetVariable("bar", bar);
      //lambda = interpreter.Parse(expression); 

      //------ 關鍵程式碼 parse
      lambda = interpreter.Parse(expression, 
        new Parameter("foo", typeof(decimal)), 
        new Parameter("bar", typeof(decimal)));

      message = $"The lambda parsed.";
    }
    catch (Exception ex)
    {
      lambda = null;
      message = $"出現例外: " + ex.GetType().Name + ", " + ex.Message;
    }
  }

  async Task HandleInvoke()
  {
    try
    {
      message = "計算中...";
      await Task.Yield();

      if(lambda is null)
      {
        message = $"lambda 未解析無法計算。";
        return;
      }

      //------ 關鍵程式碼 invoke
      var result = lambda.Invoke(foo, bar); 
      message = $"{result}";
    }
    catch (Exception ex)
    {
      message = $"出現例外: " + ex.GetType().Name + ", " + ex.Message;
    }
  }
}

(EOF)

Last updated