選單
GSS 技術部落格
在這個園地裡我們將從技術、專案管理、客戶對談面和大家分享我們多年的經驗,希望大家不管是喜歡或是有意見,都可以回饋給我們,讓我們有機會和大家對話並一起成長!
若有任何問題請來信:gss_crm@gss.com.tw
4 分鐘閱讀時間 (885 個字)

在.net上動態執行expression1微軟套件篇

unsplash-coding102

 本篇只介紹 Microsoft 所提供的套件來處理動態執行 Expression,後面幾篇會陸續介紹其他第三方開源套件


1.Roslyn - C# Scripting

初次執行時需要花費一些時間編譯,因此有效能要求的需求的話,不建議使用

  • 優點

    • 提供 C# 程式碼執行
    • 允許添加 Namespace 和類別參考 (Reference)
  • 缺點

    • 初次執行時需要花費時間編譯,第二次執行則不用花費時間
  • 評價:★★★★

 ● 安裝 NuGet 套件

Install-Package Microsoft.CodeAnalysis.CSharp.Scripting 

 ● 使用

Step.1 建立一個 Expression Evaluator,並設定引用的 Namespace 和參考的類別。

using Microsoft.CodeAnalysis.CSharp.Scripting;
using Microsoft.CodeAnalysis.Scripting;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Threading.Tasks;


public static class ExpressionEvaluator 
{
    public static async Task<object> EvalAsync(string expression, object data = null) 
    {
        // 設定 import 和 reference
        var imports = new List<string>
        {
            "System",
            "System.Math",
            "System.Linq",
            "System.Text",
            "System.Text.RegularExpressions",
            "System.Collections",
            "System.Collections.Generic"
        };
        var references = new List<Assembly>
        {
            typeof(Match).Assembly,
            typeof(Regex).Assembly
        };
        var options = ScriptOptions.Default
                                   .WithReferences(references)
                                   .WithImports(imports)
                                   .WithAllowUnsafe(false);
        
        // 執行 Expression
        var result = await CSharpScript.EvaluateAsync(expression, options);
    }    
} 

Step.2 使用前一步建立的 Expression Evaluator 執行 Expression,Expression 為 C# 程式碼

要使用的 Namespace 和類別參考 (Reference)都在 Step.1 初始化時設定

// result: "2021-04-06 10:00:00"
object dateResult = await ExpressionEvaluator.EvalAsync("DateTime.Now.ToString(\"yyyy-MM-dd HH:mm:ss\")");

// result: 178.53981633974485
object mathResult = await ExpressionEvaluator.EvalAsync("(5 * 5 * PI) + 100");

// result: "te"
object textResult = await ExpressionEvaluator.EvalAsync("\"testsplit\".Split('s')[0]"); 

 2. Adaptive Expression

為 Microsoft Bot Builder 底下的一個模組套件,而 Adaptive Card 也使用這個套件來資料綁定

Adaptive Expression 的程式語言並非 C#、JavaScript...任何一種,而是以類似 Excel Function Expression 的程式語言

除了有提供 C# 版本外,還有提供 JavaScript 的版本

  • 優點

    • 提供內建 Function 使用
    • 提供自訂 Function
  • 缺點

  • 評價:★★★★★

 ● 安裝 NuGet 套件

Install-Package AdaptiveExpressions 

 ● 使用

Step.1 建立一個 Expression Evaluator

● Adaptive Expression 有提供內建的 Function 可以使用,詳細請至 Adaptive Expressions Prebuilt Functions 微軟官方文件查看

● 如果內建的 Function 無法滿足時,可以自行加入自訂 Function

using AdaptiveExpressions;
using System;

public static class ExpressionEvaluator 
{
    public static object Eval(string expression, object data = null) 
    {
        try
        {
            // 剖析 Expression
            var adpExpression = Expression.Parse(expression);
            
            // 加入自訂 Function (Optional)
            AddCustomFunction();

            // 執行 Expression
            var (value, error) = adpExpression.TryEvaluate(data);

            if (error == null && value != null)
            {
                // 執行成功
                return value;
            }

            // 執行失敗
            return expression;
        }
        catch
        {
            // 執行失敗
            return expression;
        }
    }
    
    // 加入自訂 Function
    public static void AddCustomFunction()
    {
        // 清除 Functions (避免重複註冊)
        Expression.Functions.Clear();
        
        // 加入自訂 Function,需包含 Function Name 和 Function 實作
        Expression.Functions.Add("localNow", (args) =>
                                {                                    
                                    // 取得 Function 參數
                                    string format = "yyyy-MM-ddTHH:mm:ss.fffZ";
                                    if (args != null && args.Count > 0 && args[0] != null)
                                    {
                                        format = Convert.ToString(args[0]);
                                    }
                                    return DateTime.Now.ToString(format);
                                });
    }
} 

Step.2 使用前一步建立的 Expression Evaluator 執行 Expression (類似 Excel Function Expression)

可以傳入一個物件 (Object) 提供 Expression 執行時使用

// result: "2021-04-06 10:00:00"
object dateResult = ExpressionEvaluator.Eval("addHours(utcNow(), 8, 'yyyy-MM-dd HH:mm:ss')");

// result: 178.53981633974485
object mathResult = ExpressionEvaluator.Eval("(5 * 5 * PI) + 100", new { PI = Math.PI });

// result: [ "Hello", "World!" ]
object textResults = ExpressionEvaluator.Eval("split(Text, ' ')", new { Text = "Hello World!" });

// result: "張三丰 (武當派掌門人)"
var data =  new { 
    Name = "張三丰", 
    Detial = new { 
        Description = "武當派掌門人" 
    }
};
object stringResults = ExpressionEvaluator.Eval("concat(Name, ' (', Detial.Description, ')')", data);

// 使用自訂 Function ─ localNow('{format}')
// result: "2021-04-06 10:00:00"
object customResult = ExpressionEvaluator.Eval("localNow('yyyy-MM-dd HH:mm:ss')");
 

 3. DataTable

只能處理簡單的數學計算處理,如果需要更複雜的的處理,請考慮別的套件

  • 優點

    • 簡單使用
    • 不用額外安裝套件
  • 缺點

    • 只能處理簡單的數學計算
  • 評價:★★★

 ● 使用

// result: 2
int intResult = Convert.ToInt32(new DataTable().Compute("1 + 1", string.Empty));

// result: true
bool boolResult = Convert.ToBoolean(new DataTable().Compute("1 = 1", string.Empty));
 

 4. 其他做法

除了上述的3種做法,還有以下5種做法,但是因為我沒有深入研究,有興趣者請自行研究

[前端-小分享]在JavaScript裡多元使用 Array-Part1
Net Core Razor View 中文被自動編碼!?

相關文章

 

評論

尚無評論
已經注冊了? 這裡登入
Guest
2024/05/05, 週日

Captcha 圖像