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#语法的数学表达式计算。

 

如果认为此文对您有帮助,别忘了支持一下哦!

作者:齐飞

来源:http://youring2.cnblogs.com/

声明:本博客原创文字只代表本人工作中在某一时间内总结的观点或结论,与本人所在单位没有直接利益关系。非商业,未授权,贴子请以现状保留,转载时必须保留此段声明,且在文章页面明显位置给出原文连接。

转载:http://www.cnblogs.com/youring2/archive/2012/12/17/2822104.html

时间: 2024-10-28 13:20:54

C#动态编译计算表达式的值的相关文章

无法watch-当前方法的代码已经过优化 无法计算表达式的值

问题描述 当前方法的代码已经过优化 无法计算表达式的值 网上找的解决方案是在项目属性里不要勾选 代码优化 可是我的项目一直都没有勾选过 解决方案 你从哪看出来我使用了response.end 和 HttpContext.Current.ApplicationInstance.CompleteRequest 结束 ???? 解决方案二: 这种情况一般是使用了response.end,并将代码放在try catch里,解决办法就是将response.end去掉或正如楼主用HttpContext.Cu

asp.net-Response.End() 由于代码已经过优化或者本机框架位于调用堆栈之上,无法计算表达式的值。

问题描述 Response.End() 由于代码已经过优化或者本机框架位于调用堆栈之上,无法计算表达式的值. public void Write(string obj){ Response.Clear(); Response.Write(obj); HttpContext.Current.ApplicationInstance.CompleteRequest(); Response.End();} AJax请求自己的后台页面后台输出参数Write(""1"");报错

c++-C ++ CXX0030: 错误: 无法计算表达式的值

问题描述 C ++ CXX0030: 错误: 无法计算表达式的值 std::vector<VmbUchar_t> * v=NULL; v = new std::vector<VmbUchar_t>; v=( std::vector<VmbUchar_t> *)malloc(100); dateInfo di ; di.frameId=nFrameID;//nFrameID会自动+1 di.v=v; memcpy(di.v,&TransformedData,100

语言决不是语法的不同之.NET 版本计算表达式的值

语法 很多人会说语言只是语法的差异,事实上,大家忽略了一点选择了一种语言,语言的提供者一定会提供很多的系统库给这个语言. 接下来一个简单的例子来结合Jscript.net 和 C# 来实现对一个表达式的计算. 问题要求: 输入一串简单的表达式,输出值.比如2+4*7 返回30 注意我们全部用.net 去实现,呵呵. 1.新建一个jscript文件, CustomEval.js // JScript source codeclass CustomEval{static function eval(

stack计算表达式的值

9.52 使用stack对象处理带圆括号的表达式.遇到左圆括号时,将其标记下来.当你在一个左括号之后遇到右圆括号时,弹出stack对象中这两边括号之间的元素,直到遇到左括号,将左括号也一起弹出栈. 接着在stack对象中压入一个值,用以表明这个用一对圆括号括起来的表达式已经被替换. 程序如下: #include<iostream> #include<stack> #include<string> using namespace std; int main() { sta

求助 关于 本机框架位于堆栈顶部,因此无法计算表达式的值

问题描述 程序是点击屏幕上的按钮返回数据库中MyClass表中数据的个数代码如下:publicpartialclassForm1:Form{publicForm1(){InitializeComponent();}privatevoidbutton1_Click(objectsender,EventArgse){stringsql="selectcount(*)fromMyStudent";MessageBox.Show(SqlHelper.ExecuteScalar(sql,Comm

vc++2010创建项目失败,无法计算xxx处的属性表达式的值

问题描述 vc++2010创建项目失败,无法计算xxx处的属性表达式的值 vc++2010创建项目失败,报错如下图,求教高手提点. 解决方案 是新建的项目的话,建议重装下vs,再不行重装下系统.

重新演绎动态编译类,打造灵活多变的系统

前端时间,写过一篇博文:< C#动态编译,实现按钮功能动态配置>,里面提到了动态编译的好处,可以随时添加你要集成的功能,而不用去重新启动系统.如果系统超级大,启动需要半个小时甚至数个小时的话,用动态编译是极佳的选择. 动态编译的好处让我舍不得丢弃它,所以只好找方法来优化它了.既然每次点击需要编译,如果我把全部功能都一次性编译完毕,保存这个实例,然后每次点击,都通过这个实例去调用对应的方法,这样就完美解决了这一问题.  不多说,上代码: 动态编译类 Evaluator: using System

c语言-参照网上,自己改用链栈写了个表达式求值的代码出现的问题

问题描述 参照网上,自己改用链栈写了个表达式求值的代码出现的问题 这个代码可以编译运行,但是输入值进行计算的时候就会停止工作 附上代码: 附上代码求指导: #include #include typedef struct rope { char date; struct rope next; } node,*pnode; typedef struct rope2 { char date; struct rope2 *next; } nodes,*pnodes; typedef struct a