【问题标题】:C# Compiling User Supplied Code And UsingC# 编译用户提供的代码并使用
【发布时间】:2011-05-12 16:11:46
【问题描述】:

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

所以我一直在使用示例控制台应用程序,但遇到了问题。我已经检查了堆栈溢出和 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。 如果这不可行,我会尽我所能。

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

【问题讨论】:

    标签: c# scripting codedom system-codedom-compiler


    【解决方案1】:

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

    您可能更喜欢调用GetTypes() 来查看程序集中定义的所有类型。

    【讨论】:

    • 这样我就可以使用 Invoke 方法调用该函数。您是否知道一种将其称为“testd(5,8)”的方法?最终的希望是用户提供的函数作为 dll 的委托。
    • 另一个或多或少说同样事情的有用资源:stackoverflow.com/questions/1698870/…
    • @Tim:调用GetTypes() 并找到具有您正在寻找的功能的类型。
    • 似乎有些混乱。我可以使用调用方法调用 testd()。但我想知道是否有一种方法可以在主要访问它,我可以说 double x = testd(a,b)。
    • @Tim:不;编译器无法知道testd 是什么。即使dynamic 也不够。
    【解决方案2】:

    相信这篇文章会帮助你通过使用接口直接访问方法 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();
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2022-01-18
      • 1970-01-01
      • 2014-09-09
      • 2015-06-06
      • 2012-04-13
      • 1970-01-01
      • 2020-07-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多