![](/img/trans.png)
[英]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.