[英]C# An object reference is required for the non-static field, method, or property 'HttpContext.Request'
[英]“An object reference is required for the non-static field, method or property.” while compiling C# code at runtime
我有一个公共类“ CodeCompiler”,它使我可以在运行时编译和运行C#代码。 就像IDE一样。
当我单击“ button1”时,它将在运行时创建代码,进行编译和执行。
我的主Form1包含一个名为“ textbox1”的TextBox控件。 为了在运行时对“ textbox1”进行更改,我创建了这个button1_Click事件。 但是当我单击它时,它显示了一个运行时错误...
Compiler Errors :
Line 14,34 : An object reference is required for the non-static field, method, or property 'Compiling_CSharp_Code_at_Runtime.Form1.textBox1'
它显示了我何时编辑“ textbox1”上的文本数据。 但是,如果我尝试对其他属性(例如“大小”,“位置”)进行更改,那么请想象会发生什么!
using System;
using System.Text;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.Reflection;
namespace Compiling_CSharp_Code_at_Runtime
{
public class CodeCompiler
{
public CodeCompiler()
{
}
public object ExecuteCode(string code, string namespacename, string classname,
string functionname, bool isstatic,
string[] References1, params object[] args)
{
object returnval = null;
CompilerParameters compilerparams = new CompilerParameters();
for (int i = 0; i <= References1.GetUpperBound(0); i++)
{
compilerparams.ReferencedAssemblies.Add(References1[i]);
}
Assembly asm = BuildAssembly(code, compilerparams);
object instance = null;
Type type = null;
if (isstatic)
{
type = asm.GetType(namespacename + "." + classname);
}
else
{
instance = asm.CreateInstance(namespacename + "." + classname);
type = instance.GetType();
}
MethodInfo method = type.GetMethod(functionname);
returnval = method.Invoke(instance, args);
return returnval;
}
private Assembly BuildAssembly(string code, CompilerParameters compilerparams)
{
Microsoft.CSharp.CSharpCodeProvider provider = new CSharpCodeProvider();
ICodeCompiler compiler = provider.CreateCompiler();
compilerparams.GenerateExecutable = false;
compilerparams.GenerateInMemory = true;
CompilerResults results = compiler.CompileAssemblyFromSource(compilerparams, code);
if (results.Errors.HasErrors)
{
StringBuilder errors = new StringBuilder("Compiler Errors :\r\n");
foreach (CompilerError error in results.Errors )
{
errors.AppendFormat("Line {0},{1}\t: {2}\n", error.Line, error.Column, error.ErrorText);
}
throw new Exception(errors.ToString());
}
else
{
return results.CompiledAssembly;
}
}
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
CodeCompiler cc = new CodeCompiler();
string SourceCode1 = @"
using Compiling_CSharp_Code_at_Runtime;
using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Drawing;
namespace N1
{
public class C1
{
public static void F1(string st1, string st2)
{
Compiling_CSharp_Code_at_Runtime.Form1.textBox1.Text += ""This is a DEMO "" st1 + st2.ToUpper();
}
}
}";
string namespace1 = "N1", class1 = "C1", function1 = "F1";
bool IsStatic = true;
object o = cc.ExecuteCode(SourceCode1, namespace1, class1, function1, IsStatic, new string[] { "Compiling CSharp Code at Runtime.exe", "System.Windows.Forms.dll", "System.Drawing.dll", "System.ComponentModel.dll", "System.dll" }, "arg1", "arg2");
}
}
}
我在这个建议为的站点上发现了许多与此问题相关的问题:
“看来我正在从静态方法中调用非静态属性。我应该使该属性成为静态属性,或者创建Form1的实例。”
但是,即使在运行时创建Form1实例也很困难!
问题似乎是您根本没有将要在其上执行代码的Form1
引用传递给CodeCompiler
。 您在Form1
中调用它的事实不会更改任何内容-对象不会自动使用它们学习有关该对象的任何信息。 (如果这样做的话,事情将会复杂得多。)
您访问Form1
方式也不正确-您正在使用类型名(顺便说一句,它是毫无意义的完全限定路径,因为类C1
与Form1
不在同一个命名空间中,但您要包含Form1
'通过using
)来引用已编译代码中的s命名空间,以引用该类型的非静态成员。 该实例成员textBox1
类型Form1
只能从一些实例来访问,但有访问Form1 的对象不符合逻辑的方式。 如果您实例化了10个该怎么办? 如何决定在这10个电话中,哪一个返回您的通话?
如果您想继续沿着这条道路走,应该做些什么(我不确定为什么要在C#中模仿eval()),您将放弃很多使C#变得简单易用的安全性(可以使用)传递给您想要在CodeCompiler的构造函数或ExecuteCode方法中更改的Form1
实例的引用。 我认为后者可能更有意义。
您应该更改SourceCode1使其看起来像这样(这也可以修复原始代码中的错字,恢复丢失的+
字符):
string SourceCode1 = @"
using Compiling_CSharp_Code_at_Runtime;
using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Drawing;
namespace N1
{
public class C1
{
public static void F1(string st1, string st2, Form1 formToExecuteOn)
{
formToExecuteOn.textBox1.Text +=
""This is a DEMO "" + st1 + st2.ToUpper();
}
}
}";
然后像这样调用ExecuteCode()
方法:
object o = cc.ExecuteCode(SourceCode1, namespace1, class1, function1, IsStatic,
new string[] { "Compiling CSharp Code at Runtime.exe",
"System.Windows.Forms.dll", "System.Drawing.dll",
"System.ComponentModel.dll", "System.dll" },
"arg1", "arg2", this);
这将编译代码,以便要使用的Form1
实例在调用时可以传递给该方法。 在实际上为方法调用传递的参数列表(即最后一个参数this
)中提供了对该Form1
实例的引用。
当然,即使可行,它也只允许您在Form1
对象上执行代码。 更大的一点是,如果您要走这条路,则需要将对您想要以某种方式更改的任何内容的引用传递给CodeCompiler
。 我不知道对象是否objectToChange
反而会工作的formToChange
,多少信息,编译器将需要约你传递,以在其上执行代码的对象。
再说一次,感觉:您需要一个非常非常独特的用例,以使其中的任何一个都可以很好地利用时间或理智。 (您每次想运行任何东西时 ,都必须将七个精确构造的对象(主要是字符串)传递给ExecuteCode()
!)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.