现在的位置: 首页 > 综合 > 正文

CodeDom计算器——动态计算数学表达式的实现

2011年11月23日 ⁄ 综合 ⁄ 共 3220字 ⁄ 字号 评论关闭

序言:前几天整理资料时发现以前翻译的一篇关于CodeDom的文章,虽然题材比较老了,但还是可能对部分兄弟有用,贴出来与大家共享,不妥之处敬请指出。原文来自CSharpCornerhttp://www.c-sharpcorner.com/UploadFile/mgold/CodeDomCalculator08082005003253AM/CodeDomCalculator.aspx

介绍:

借助CodeDomReflection我们可以动态编译C#代码并使之在程序中任何地方都能运行。这个强大的特性允许我们创建在Windows窗体甚至C#代码行中都可以运算数学表达式的CodeDom计算器。首先我们需要借助System.Math类来进行计算,但我们并不需要在算式前加上Math. 前缀,下面将向您展现CodeDom计算器是如何实现的。

 



1 – 运行中的CodeDom计算器

 

用法:

CodeDom可依下列两种方法使用:

1、用C#语法输入你要计算的数学表达式

2、写一个计算复杂算式的C#代码块

第一种方法仅需要按图2中的方法输入算式即可。

 


2 – CodeDom计算器中运算一个较长的算式

在第二种方法中我们实现的手段略有差异。最上面一行写一个answer加上分号,之后你就可以写任何C#代码,在代码片断的末端将你需要得到的答案赋予answer变量。在写代码时同上也不用加Math类前缀,图3是用CodeDom求从110的和的示例:

 


3 – CodeDom计算从110的和

 

创建并运行Calculator

运算表达式的下面几步是:

1、使用CodeDom依据算式创建C#代码

2、使用CodeDom编译器将这段代码编译为程序集

3、创建一个Calculator类的实例

4、调用Calculator类中的Calculate方法得到答案

下表就是我们要创建的CodeDom类,Calculate方法将包含我们输入CodeDom计算器的数学表达式。

 


4 – UML反工得到的Calculator

事实上图3中用到的CodeDom程序集是由下列代码创建的。下一节我们将讲述更多关于如何创建包含CodeDom所有方法的类,这些方法真是酷毙了。真如您所见,我们的表达式被传入Calculate方法中。我们需要将answer;放到第一行是为了在Calculate方法强制置入一个哑元行来引入较大的代码块(这个哑元行是Answer = answer;)。如果我们输入一个简单的表达式如11,在代码内将产生一行Answer = 1 + 1;

列表 1 – CodeDom为计算器产生的代码

 namespace ExpressionEvaluator {

    using System;
    using System.Windows.Forms;

    public class Calculator
    {       
        private double answer;       

        /// Default Constructor for class
        public Calculator()
        {
            //TODO: implement default constructor
        }

       

        // The Answer property is the returned result
        public virtual double Answer
        {
            get
               {
                return this.answer;
               }

            set
              {
                this.answer = value;
              }
        }

        /// Calculate an expression
        public virtual double Calculate()
        {
          Answer = answer;
          for (int i = 1; i <= 10; i++)
              answer = answer + i;

            return this.Answer;
        }

    }
}

代码分析

点击计算按钮后代码产生、编译、运行。  列表2 展示了按顺序执行这几步的calculate event handler。尽管这不是全部的代码,所有的步骤已经在BuildClass, CompileAssemblyRunCode方法里全部包括:.

列表 2 – 计算数学表达式的Event Handler

            private void btnCalculate_Click(object sender, System.EventArgs e)
            {
            // Blank out result fields and compile result fields
            InitializeFields(); 

            // change evaluation string to pick up Math class members
           string expression = RefineEvaluationString(txtCalculate.Text);

            // build the class using codedom
            BuildClass(expression);

             // compile the class into an in-memory assembly.
            // if it doesn't compile, show errors in the window
            CompilerResults results = CompileAssembly();

            // write out the source code for debugging purposes
            Console.WriteLine("...........................\r\n");
            Console.WriteLine(_source.ToString());

 

            // if the code compiled okay,
            // run the code using the new assembly (which is inside the results)
            if (results != null && results.CompiledAssembly != null)
            {
                // run the evaluation function
                RunCode(results);
            }
        }


CodeDom
看起来怎么样呢如果你仔细观察过CodeDom中的类, 就会发现它们几乎就是违反语法的。每个构造器使用其他CodeDom对象来构造自己并构造其他语法片断的合成物。表1展示了我们在这个工程中构造程序集用到的所有类和他们各自的用途。

CodeDom 对象

用途

CSharpCodeProvider

生成C#代码的Provider

CodeNamespace

构造名称空间的类

CodeNamespaceImport

创建调用申明

CodeTypeDeclaration

创建类结构

CodeConstructor

创建构造器

CodeTypeReference

创建一个类型的引用

CodeCommentStatement

创建C#注释

CodeAssignStatement

抱歉!评论已关闭.