C#動態編譯計算表達式的值


C#動態編譯計算表達式的值,是通過System.CodeDom.Compiler命名空間下的相關類來實現的。其步驟大致為:

1.將表達式包裝成為可編譯的C#代碼

2.使用反射調用上一步編譯的代碼。

示例如下:在界面上放一個TextBox,用來輸入表達式;放一個按鈕,用來相應用戶點擊,以進行表達式的計算;在另外一個TextBox中顯示計算結果。對應的xaml代碼如下:

<Window x:Class="SampleCodeDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="403" Width="663" Loaded="Window_Loaded">
    <Grid>
        <TextBox Height="87" HorizontalAlignment="Left" Margin="12,12,0,0" Name="txtExpression" VerticalAlignment="Top" Width="617" TextWrapping="Wrap" />
        <Button Content="計算" Height="23" HorizontalAlignment="Left" Margin="554,114,0,0" Name="btnCalculate" VerticalAlignment="Top" Width="75" Click="btnCalculate_Click" />
        <TextBox Height="48" HorizontalAlignment="Left" Margin="12,157,0,0" Name="txtResult" VerticalAlignment="Top" Width="617" IsEnabled="False" TextWrapping="Wrap" />
    </Grid>
</Window>

在后台代碼中,首先添加一下引用:

using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.Reflection;

剩余的代碼如下:

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            this.txtExpression.Focus();
        }

        private void btnCalculate_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                string expression = this.txtExpression.Text.Trim();
                this.txtResult.Text = this.ComplierCode(expression).ToString();
            }
            catch (Exception ex)
            {
                this.txtResult.Text = ex.Message;
            }
        }

        private object ComplierCode(string expression)
        {
            string code = WrapExpression(expression);

            CSharpCodeProvider csharpCodeProvider = new CSharpCodeProvider();

            //編譯的參數
            CompilerParameters compilerParameters = new CompilerParameters();
            //compilerParameters.ReferencedAssemblies.AddRange();
            compilerParameters.CompilerOptions = "/t:library";
            compilerParameters.GenerateInMemory = true;
            //開始編譯
            CompilerResults compilerResults = csharpCodeProvider.CompileAssemblyFromSource(compilerParameters, code);
            if (compilerResults.Errors.Count > 0)
                throw new Exception("編譯出錯!");

            Assembly assembly = compilerResults.CompiledAssembly;
            Type type = assembly.GetType("ExpressionCalculate");
            MethodInfo method = type.GetMethod("Calculate");
            return method.Invoke(null, null);
        }

        private string WrapExpression(string expression)
        {
            string code = @"
                using System;

                class ExpressionCalculate
                {
                    public static DateTime start_dt = Convert.ToDateTime(""{start_dt}"");
                    public static DateTime end_dt = Convert.ToDateTime(""{end_dt}"");
                    public static DateTime current_dt = DateTime.Now;

                    public static object Calculate()
                    {
                        return {0};
                    }
                }
            ";

            return code.Replace("{0}", expression);
        }

簡單的說明一下,WrapExpression方法用來包裝表達式,使其可以被代碼編譯器編譯通過。ComplierCode方法用來編譯,並通過反射執行代碼。其它是兩個事件的處理方法,無需多說。

在上面的示例中可以實現動態計算符合C#語法的數學表達式計算。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM