C# 编译用户提供的代码并使用
本文关键字:代码 编译 用户 | 更新日期: 2023-09-27 17:56:29
我要做的是允许用户在文本框中编写方法并让我的代码调用该方法。这最终将用于演示小程序,以便在给定目标函数的情况下进行优化。
所以我一直在使用一个示例控制台应用程序,但我遇到了问题。我已经检查了堆栈溢出和代码项目以及其他来源,并且已经到了可以编译代码的地步。但是我不知道如何调用它,只能访问一种方法。
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。如果这不可行,我会在这一点上采取我能得到的。
任何帮助或指导将不胜感激。谢谢。
您需要
在GetType
调用中包含命名空间。
(或从源中删除命名空间)
您可能更愿意调用 GetTypes()
并改为查看程序集中定义的所有类型。
我相信
本文将帮助您通过使用接口直接访问该方法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();
}
}
}