C# 编译用户提供的代码并使用

发布于 2024-11-06 14:34:57 字数 2933 浏览 3 评论 0原文

我想做的是允许用户在文本框中编写一个方法,并让我的代码调用该方法。这最终将在演示小程序中用于给定目标函数的优化。

因此,我一直在使用示例控制台应用程序,但遇到了麻烦。我已经检查了堆栈溢出和 codeproject 以及其他来源,并且已经达到了可以编译代码的程度。但我不知道如何调用它并且只访问一个方法。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using System.Reflection;

namespace CodeCompilerTest
{
    class Program
    {
        static void Main(string[] args)
        {
            CodeDomProvider codeProvider = CodeDomProvider.CreateProvider("CSharp");

            CompilerParameters parameters = new CompilerParameters();
            //parameters.GenerateExecutable = false;
            parameters.GenerateInMemory = true;
            //parameters.OutputAssembly = "Output.dll";

            string SourceString = @"
                                   using System;
                                   using System.Collections.Generic;
                                   using System.Text;

                                   namespace testone 
                                   {
                                        public class myclass
                                        {
                                            public double Main()
                                            {
                                                return testd(5,8);
                                            }

                                            public double testd(double a, double b)
                                            { 
                                                return a+b;
                                            } 
                                        } 
                                    }";

            CompilerResults results = codeProvider.CompileAssemblyFromSource(parameters, SourceString);

            if (results.Errors.Count > 0)
            {
                foreach (CompilerError CompErr in results.Errors)
                {
                    Console.WriteLine("Line number " + CompErr.Line + ", Error Number: " + CompErr.ErrorNumber + ", '" + CompErr.ErrorText + ";");
                }
                Console.ReadLine();
            }

            Assembly mAssembly = results.CompiledAssembly;
            Type scripttype = mAssembly.GetType("myclass");
            Object rslt = new Object();
            Object[] argin = {5, 8};
            //rslt  = scripttype.GetMethod("Main").Invoke(null, null);
            rslt = scripttype.InvokeMember("Main", BindingFlags.InvokeMethod | BindingFlags.Public |BindingFlags.Static, null, null, null);
            Console.WriteLine(((double)rslt).ToString());
            Console.ReadLine();
        }
    }
}

我尝试了不同的组合来调用方法上的 Invoke 并不断收到错误。 我想要做的是让用户定义一个这样的函数:

public double funcname(double x, double y)
{
    return x+y;
}

然后我可以直接调用 funcname 。 如果这是不可能的,我会采取我现在能得到的。

任何帮助或指导将不胜感激。 谢谢。

What I'm trying to do is allow a user to write a method in a textbox and have my code call that method. This will eventually be used in a demo applet for optimization given a goal function.

So I've been working with a sample console application but I'm having trouble. I've checked stack overflow and codeproject and other sources, and have got to the point where I can compile the code. But I'm lost at how to call it and only access a method.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using System.Reflection;

namespace CodeCompilerTest
{
    class Program
    {
        static void Main(string[] args)
        {
            CodeDomProvider codeProvider = CodeDomProvider.CreateProvider("CSharp");

            CompilerParameters parameters = new CompilerParameters();
            //parameters.GenerateExecutable = false;
            parameters.GenerateInMemory = true;
            //parameters.OutputAssembly = "Output.dll";

            string SourceString = @"
                                   using System;
                                   using System.Collections.Generic;
                                   using System.Text;

                                   namespace testone 
                                   {
                                        public class myclass
                                        {
                                            public double Main()
                                            {
                                                return testd(5,8);
                                            }

                                            public double testd(double a, double b)
                                            { 
                                                return a+b;
                                            } 
                                        } 
                                    }";

            CompilerResults results = codeProvider.CompileAssemblyFromSource(parameters, SourceString);

            if (results.Errors.Count > 0)
            {
                foreach (CompilerError CompErr in results.Errors)
                {
                    Console.WriteLine("Line number " + CompErr.Line + ", Error Number: " + CompErr.ErrorNumber + ", '" + CompErr.ErrorText + ";");
                }
                Console.ReadLine();
            }

            Assembly mAssembly = results.CompiledAssembly;
            Type scripttype = mAssembly.GetType("myclass");
            Object rslt = new Object();
            Object[] argin = {5, 8};
            //rslt  = scripttype.GetMethod("Main").Invoke(null, null);
            rslt = scripttype.InvokeMember("Main", BindingFlags.InvokeMethod | BindingFlags.Public |BindingFlags.Static, null, null, null);
            Console.WriteLine(((double)rslt).ToString());
            Console.ReadLine();
        }
    }
}

I've tried different combinations on how to call the Invoke on the method and keep getting errors.
What I want to be able to do is have the user define a function like this:

public double funcname(double x, double y)
{
    return x+y;
}

And then I could just call funcname directly.
If this is not doable, I'll take what I can get at this point.

Any help or guidance would be appreciated.
Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

如此安好 2024-11-13 14:34:57

您需要在 GetType 调用中包含命名空间。
(或者从源中删除命名空间)

您可能更愿意调用 GetTypes() 并查看程序集中定义的所有类型。

You need to include the namespace in the GetType call.
(Or remove the namespace from the source)

You may prefer to call GetTypes() and see all of the types defined in the assembly instead.

初相遇 2024-11-13 14:34:57

相信这篇文章会帮助你通过接口直接访问方法
http://www.codeproject.com/Articles/26312/Dynamic -Code-Integration-with-CodeDom

也许下面的内容与您的请求不直接相关,但我相信您需要使用 Activator 创建该类的实例,以便您可以调用testd方法
我的意思是您定义的代码没有对象,只有类定义。
我还使用了 GetTypes()[0] 因为 GetType() 对我不起作用

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using System.Reflection;

namespace CodeCompilerTest
{
    class Program
    {
        static void Main(string[] args)
        {
            CodeDomProvider codeProvider = CodeDomProvider.CreateProvider("CSharp");

            CompilerParameters parameters = new CompilerParameters();
            //parameters.GenerateExecutable = false;
            parameters.GenerateInMemory = true;
            //parameters.OutputAssembly = "Output.dll";

            string SourceString = @"
                                   using System;
                                   using System.Collections.Generic;
                                   using System.Text;

                                   namespace testone 
                                   {
                                        public class myclass
                                        {
                                            public double testd(double a, double b)
                                            { 
                                                return a+b;
                                            } 
                                        } 
                                    }";

            CompilerResults results = codeProvider.CompileAssemblyFromSource(parameters, SourceString);

            if (results.Errors.Count > 0)
            {
                foreach (CompilerError CompErr in results.Errors)
                {
                    Console.WriteLine("Line number " + CompErr.Line + ", Error Number: " + CompErr.ErrorNumber + ", '" + CompErr.ErrorText + ";");
                }
                Console.ReadLine();
            }

            Assembly mAssembly = results.CompiledAssembly;
            Type scripttype = mAssembly.GetTypes()[0];
            Object myObject = Activator.CreateInstance(scripttype);
            double  rsltd = 0.0;
            Object[] argin = { 5.0, 8.0 };
            rsltd  =(double) scripttype.GetMethod("testd").Invoke(myObject,argin);
          //  object rslt = new object();
           // rslt = scripttype.InvokeMember("testd", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null, null, null);
       Console.WriteLine(rsltd.ToString());
       Console.ReadLine();
        }
    }
}

I believe this article will help you to access the method directly through using interfaces
http://www.codeproject.com/Articles/26312/Dynamic-Code-Integration-with-CodeDom

Maybe the below is not relevant directly to your request, but I believe that you need to use Activator to create an instance of the class so you can call the testd method
I mean your code defined has no object, just class definition.
Also I used GetTypes()[0] because GetType() didn't work for me

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using System.Reflection;

namespace CodeCompilerTest
{
    class Program
    {
        static void Main(string[] args)
        {
            CodeDomProvider codeProvider = CodeDomProvider.CreateProvider("CSharp");

            CompilerParameters parameters = new CompilerParameters();
            //parameters.GenerateExecutable = false;
            parameters.GenerateInMemory = true;
            //parameters.OutputAssembly = "Output.dll";

            string SourceString = @"
                                   using System;
                                   using System.Collections.Generic;
                                   using System.Text;

                                   namespace testone 
                                   {
                                        public class myclass
                                        {
                                            public double testd(double a, double b)
                                            { 
                                                return a+b;
                                            } 
                                        } 
                                    }";

            CompilerResults results = codeProvider.CompileAssemblyFromSource(parameters, SourceString);

            if (results.Errors.Count > 0)
            {
                foreach (CompilerError CompErr in results.Errors)
                {
                    Console.WriteLine("Line number " + CompErr.Line + ", Error Number: " + CompErr.ErrorNumber + ", '" + CompErr.ErrorText + ";");
                }
                Console.ReadLine();
            }

            Assembly mAssembly = results.CompiledAssembly;
            Type scripttype = mAssembly.GetTypes()[0];
            Object myObject = Activator.CreateInstance(scripttype);
            double  rsltd = 0.0;
            Object[] argin = { 5.0, 8.0 };
            rsltd  =(double) scripttype.GetMethod("testd").Invoke(myObject,argin);
          //  object rslt = new object();
           // rslt = scripttype.InvokeMember("testd", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null, null, null);
       Console.WriteLine(rsltd.ToString());
       Console.ReadLine();
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文