简体   繁体   English

“在运行时编译C#代码时,非静态字段,方法或属性需要对象引用。”

[英]“An object reference is required for the non-static field, method or property.” while compiling C# code at runtime

I have a public class, "CodeCompiler", which allows me to compile and run C# code at run-time. 我有一个公共类“ CodeCompiler”,它使我可以在运行时编译和运行C#代码。 Just like IDEs work. 就像IDE一样。

When I click the "button1" it creates code at run-time, compiles and executes. 当我单击“ button1”时,它将在运行时创建代码,进行编译和执行。

My main Form1 contains a TextBox control called "textbox1". 我的主Form1包含一个名为“ textbox1”的TextBox控件。 In order to make changes on that "textbox1" by runtime I made this button1_Click event. 为了在运行时对“ textbox1”进行更改,我创建了这个button1_Click事件。 But when I click it, it shows me a run-time error... 但是当我单击它时,它显示了一个运行时错误...

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'

It showed me when I was editing the text data on that "textbox1". 它显示了我何时编辑“ textbox1”上的文本数据。 But if I will try to make changes about other property like "Size", "Location" then imagine what will happen! 但是,如果我尝试对其他属性(例如“大小”,“位置”)进行更改,那么请想象会发生什么!

 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");
        }
    }
}

I found many problems related to this problem on this site where a suggestion was: 我在这个建议为的站点上发现了许多与此问题相关的问题:

"It looks like I am calling a non static property from a static method. I should either make the property static, or create an instance of Form1." “看来我正在从静态方法中调用非静态属性。我应该使该属性成为静态属性,或者创建Form1的实例。”

But even creation an instance of Form1 was difficult at runtime! 但是,即使在运行时创建Form1实例也很困难!

The problem appears to be that you're not passing reference to the Form1 on which you want code to be executed to CodeCompiler at all. 问题似乎是您根本没有将要在其上执行代码的Form1引用传递给CodeCompiler The fact that you're calling it within your Form1 doesn't change anything - objects don't automatically learn anything about the object using them. 您在Form1中调用它的事实不会更改任何内容-对象不会自动使用它们学习有关该对象的任何信息。 (If they did, things would be a lot more complicated.) (如果这样做的话,事情将会复杂得多。)

The way you're accessing Form1 is also incorrect - you're using the typename (by the way, as a fully-qualified path which is pointless, because while the class C1 is not in the same namespace as Form1 , you include Form1 's namespace in the compiled code via using ) to refer to a non-static member of the type. 您访问Form1方式也不正确-您正在使用类型名(顺便说一句,它是毫无意义的完全限定路径,因为类C1Form1不在同一个命名空间中,但您要包含Form1 '通过using )来引用已编译代码中的s命名空间,以引用该类型的非静态成员。 The instance member textBox1 of the type Form1 can be accessed only from some instance, but there's no logical way to access the Form1 object. 该实例成员textBox1类型Form1只能从一些实例来访问,但有访问Form1 对象不符合逻辑的方式。 What if you'd instantiated 10 of them? 如果您实例化了10个该怎么办? How would the decision be made which of those 10 to return to your call? 如何决定在这10个电话中,哪一个返回您的通话?

What you should do, if you want to continue down this path (and I'm not really sure why you're trying to mimic eval() in C# - you're throwing away a lot of the safety that makes C# nice and easy to work with), is pass a reference to the Form1 instance you want altered either in the constructor of CodeCompiler or in the ExecuteCode method. 如果您想继续沿着这条道路走,应该做些什么(我不确定为什么要在C#中模仿eval()),您将放弃很多使C#变得简单易用的安全性(可以使用)传递给您想要在CodeCompiler的构造函数或ExecuteCode方法中更改的Form1实例的引用。 I think the latter would probably make more sense. 我认为后者可能更有意义。

You should change your SourceCode1 so that it looks like this (this also fixes a typo in the original code, restoring a missing + character): 您应该更改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();
            }
        }
    }";

Then call the ExecuteCode() method like this: 然后像这样调用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);

This will compile the code such that the Form1 instance to be used can be passed to the method when it's invoked. 这将编译代码,以便要使用的Form1实例在调用时可以传递给该方法。 And the reference to that Form1 instance is provided in the argument list that is actually passed for the method invocation (ie the last argument, this ).. 在实际上为方法调用传递的参数列表(即最后一个参数this )中提供了对该Form1实例的引用。

Granted, even if that works, it'll only allow you to execute code on Form1 objects. 当然,即使可行,它也只允许您在Form1对象上执行代码。 The greater point of this is that if you're going to go down this path, you need to be passing reference to anything you want altered to CodeCompiler somehow. 更大的一点是,如果您要走这条路,则需要将对您想要以某种方式更改的任何内容的引用传递给CodeCompiler I'm not sure whether object objectToChange would work instead of formToChange , and how much information the compiler is going to need about the object you're passing in order to execute code on it. 我不知道对象是否objectToChange反而会工作的formToChange ,多少信息,编译器将需要约你传递,以在其上执行代码的对象。

And once more, for feeling: you need a very, very unique use case to make any of this even remotely a good use of time or sanity. 再说一次,感觉:您需要一个非常非常独特的用例,以使其中的任何一个都可以很好地利用时间或理智。 (You have to pass seven precisely-constructed objects, mostly strings, to ExecuteCode() every single time you want to run anything!) (您每次想运行任何东西 ,都必须将七个精确构造的对象(主要是字符串)传递给ExecuteCode() !)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 C# 非静态字段、方法或属性“HttpContext.Request”需要对象引用 - C# An object reference is required for the non-static field, method, or property 'HttpContext.Request' C#“非静态字段,方法或属性需要对象引用” - C# “An object reference is required for the non-static field, method, or property” C#中出错:“非静态字段,方法或属性需要对象引用” - Error in C#: “An object reference is required for the non-static field, method, or property” C#修复错误:“非静态字段,方法或属性需要对象引用” - C# Fixing error: “An object reference is required for the non-static field, method, or property” 问题“非静态字段,方法或属性需要对象引用” c# - Issue with “An object reference is required for the non-static field, method, or property” c# C#错误:非静态字段,方法或属性需要对象引用 - C# Error: Object reference is required for the non-static field, method, or property 为什么我在C#中得到“非静态字段,方法或属性需要对象引用”错误? - Why am I getting “object reference is required for the non-static field, method, or property” error in C#? C# 错误:“非静态字段、方法或属性需要对象引用” - C# error: "An object reference is required for the non-static field, method, or property" C# XNA 非静态字段、方法或属性需要 object 引用 - C# XNA An object reference is required for the non-static field, method, or property C# Regex:非静态字段、方法或属性“Regex.Match(string)”需要对象引用 - C# Regex: An object reference is required for the non-static field, method, or property 'Regex.Match(string)'
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM