当前位置:  开发笔记 > 编程语言 > 正文

是否可以在.NET中运行时编译和执行新代码?

如何解决《是否可以在.NET中运行时编译和执行新代码?》经验,为你挑选了4个好方法。

注意:数学表达式评估不是这个问题的焦点.我想在.NET中运行时编译和执行新代码. 话虽如此...

我想允许用户在文本框中输入任何等式,如下所示:

x = x / 2 * 0.07914
x = x^2 / 5

并将该等式应用于传入的数据点.输入数据点由x表示,每个数据点由用户指定的等式处理.我多年前做过,但我不喜欢这个解决方案,因为它需要为每次计算解析等式的文本:

float ApplyEquation (string equation, float dataPoint)
{
    // parse the equation string and figure out how to do the math
    // lots of messy code here...
}

当您处理大量数据点时,这会引入相当多的开销.我希望能够在飞行中将方程转换为函数,这样它只需要解析一次.它看起来像这样:

FunctionPointer foo = ConvertEquationToCode(equation);
....
x = foo(x);  // I could then apply the equation to my incoming data like this

函数ConvertEquationToCode将解析方程并返回指向应用适当数学的函数的指针.

该应用程序基本上是在运行时编写新代码.这可能与.NET有关吗?



1> raven..:

是! 使用Microsoft.CSharp,System.CodeDom.Compiler和System.Reflection名称空间中的方法.这是一个简单的控制台应用程序,它使用一种方法("Add42")编译一个类("SomeClass"),然后允许您调用该方法.这是一个简单的例子,我格式化以防止滚动条出现在代码显示中.它只是演示在运行时编译和使用新代码.

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

namespace RuntimeCompilationTest {
    class Program
    {
        static void Main(string[] args) {
            string sourceCode = @"
                public class SomeClass {
                    public int Add42 (int parameter) {
                        return parameter += 42;
                    }
                }";
            var compParms = new CompilerParameters{
                GenerateExecutable = false, 
                GenerateInMemory = true
            };
            var csProvider = new CSharpCodeProvider();
            CompilerResults compilerResults = 
                csProvider.CompileAssemblyFromSource(compParms, sourceCode);
            object typeInstance = 
                compilerResults.CompiledAssembly.CreateInstance("SomeClass");
            MethodInfo mi = typeInstance.GetType().GetMethod("Add42");
            int methodOutput = 
                (int)mi.Invoke(typeInstance, new object[] { 1 }); 
            Console.WriteLine(methodOutput);
            Console.ReadLine();
        }
    }
}


@JonathanNappee:我很高兴发现如何做到这一点,我没有说它很棒.我很想看到你的性能提升!

2> Brian Schmit..:

你可以试试这个:Calculator.Net

它将评估数学表达式.

从发布它将支持以下内容:

MathEvaluator eval = new MathEvaluator();
//basic math
double result = eval.Evaluate("(2 + 1) * (1 + 2)");
//calling a function
result = eval.Evaluate("sqrt(4)");
//evaluate trigonometric 
result = eval.Evaluate("cos(pi * 45 / 180.0)");
//convert inches to feet
result = eval.Evaluate("12 [in->ft]");
//use variable
result = eval.Evaluate("answer * 10");
//add variable
eval.Variables.Add("x", 10);            
result = eval.Evaluate("x * 10");

下载页面 并根据BSD许可证分发.


您将需要查看CodeDom命名空间,然后可以在运行时编译代码.

3> rice..:

是的,绝对可以让用户在文本框中键入C#,然后编译该代码并在您的应用程序中运行它.我们在工作中这样做是为了允许自定义业务逻辑.

这是一篇文章(我只是撇去它),它应该让你开始:

http://www.c-sharpcorner.com/UploadFile/ChrisBlake/RunTimeCompiler12052005045037AM/RunTimeCompiler.aspx



4> baretta..:

您还可以从空的"虚拟"XML流创建System.Xml.XPath.XPathNavigator,并使用XPath评估程序计算表达式:

static object Evaluate ( string xp )
{
  return _nav.Evaluate ( xp );
}
static readonly System.Xml.XPath.XPathNavigator _nav
  = new System.Xml.XPath.XPathDocument (
      new StringReader ( "" ) ).CreateNavigator ( );

如果要注册要在此表达式中使用的变量,可以动态构建可以在带有XPathNodeIterator的Evaluate重载中传递的XML.


  2.151
  231.2

然后,您可以编写类似"x/2*0.07914"的表达式,然后x是XML上下文中节点的值.另一个好处是,您可以访问所有XPath核心功能,包括数学和字符串操作方法,以及更多内容.

如果你想进一步,你甚至可以构建自己的XsltCustomContext(或在这里按需发布帖子),你可以在其中解析对扩展函数和变量的引用:

object result = Evaluate ( "my:func(234) * $myvar" );

my:func映射到C#/ .NET方法,该方法采用double或int作为参数.myvar在XSLT上下文中注册为变量.

推荐阅读
LEEstarmmmmm
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有