简体   繁体   English

如何从另一个类的静态方法(即只有一个对象)调用实例方法?

[英]How do I call an instance method from another classes' static method (i.e. have only one object)?

my form1 class contains a bunch of data that I need to save, so there should only be one instance of it running at a time. 我的form1类包含一堆需要保存的数据,因此一次只能运行一个实例。

public partial class Form1 : Form
{
    public string form1string = "I really need to save this data";

    public Form1()
    {
        InitializeComponent();


        // Even if I pass my form1 object here I still can't access it from
        // the upcoming static methods.
        InterceptKeys hook = new InterceptKeys();
    }

InterceptKeys, which is not my code, contains a bunch of static methods required for keyboard hooks. InterceptKeys(不是我的代码)包含键盘钩子所需的一堆静态方法。

private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
    if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
    {
       int trueKeyPressed = Marshal.ReadInt32(lParam);

       if (Form1.mirror)
       {
           Form1.newKeyPress(trueKeyPressed);
           return (IntPtr)1;
       }
    }
    return CallNextHookEx(_hookID, nCode, wParam, lParam);
 }

Because the HookCallBack method is static, Form1.newKeyPress() needs to be static as well. 因为HookCallBack方法是静态的,所以Form1.newKeyPress()也需要是静态的。

But if newKeyPress in static, I can't access the data that I need! 但是,如果newKeyPress处于静态状态,则无法访问所需的数据! I wouldn't want to declare a new form1 object here, as that would give me different versions of the data. 我不想在这里声明一个新的form1对象,因为那样会给我不同版本的数据。 Correct? 正确?

I'm not an Object Oriented Expert. 我不是面向对象的专家。 How should I format this, to ensure that all of the InterceptKey's form1 method calls are going to THE form1 object that I want? 我应该如何格式化它,以确保所有InterceptKey的form1方法调用都转到我想要的form1对象?

Thanks, please let me know if there's any more info that you need! 谢谢,如果需要更多信息,请告诉我!

You have two design issues: 您有两个设计问题:

How to call an instance method from a static method 如何从静态方法调用实例方法

Because the HookCallBack method is static, Form1.newKeyPress() needs to be static as well. 因为HookCallBack方法是静态的,所以Form1.newKeyPress()也需要是静态的。

You can pass in an instance of your main form to your HookCallBack method, you'd just need to add an additional parameter to your static method: 您可以将主窗体的实例传递给HookCallBack方法,只需向静态方法添加一个附加参数即可:

private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam, Form1 form)
{
   // ...
}

This is actually the preferred strategy. 这实际上是首选策略。 Wherever your methods and classes have dependencies on other objects, you should pass your dependencies into your methods instead of pulling them from global state. 无论您的方法和类对其他对象有依赖关系,都应将依赖关系传递给方法,而不要从全局状态中拉出它们。

Barring that, you can loop through the Application.OpenForms collection and find the form you're looking for as follows: 除非如此,否则您可以遍历Application.OpenForms集合并找到您要查找的表单,如下所示:

var form = Application.OpenForms.OfType<Form1>().First();
form.newKeyPress();

How to have one instance of a form open at one time 如何一次打开一个表单实例

Other people have suggested making your form static -- that's one approach, but its a bad approach. 其他人建议将您的表单静态化-这是一种方法,但这是一种不好的方法。 Static forms don't get garbage collected when their disposed, you have to implement your own init/reset methods when you show/hide the form, if the static form has references to other objects then your app will slowly leak memory, among other things . 静态形式没有得到收集垃圾的处置时,你必须实现自己的init /复位的方法,当你显示/隐藏表单,如果静态形式有那么你的应用程序会慢慢泄漏内存到其他对象的引用, 除其他事项外 I actually recommend something like this: 我实际上建议这样的事情:

class FormFactory
{
    public Form1 GetForm1()
    {
        return Application.OpenForms.OfType<Form1>().FirstOrDefault ?? new Form1();
    }
}

So your FormFactory controls the lifetime of your form, now you can get an existing or new instance of Form1 using new FormFactory.GetForm1() . 因此,FormFactory控制着表单的生命周期,现在您可以使用new FormFactory.GetForm1()获得Form1的现有实例或新实例。

Passing keypresses to other forms 将按键传递给其他形式

It occurs to me that you're basically just passing keypresses to your form, which implies a kind of basic message notification / observer pattern. 在我看来,您基本上只是将按键传递给表单,这意味着一种基本的消息通知/观察者模式。 Maybe you just need a better design pattern. 也许您只需要一个更好的设计模式。 Try the following: 请尝试以下操作:

public class MessageHooks
{
    public static event Action<int> OnHookCallback;

    private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
    {
        if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
        {
            int trueKeyPressed = Marshal.ReadInt32(lParam);
            if (OnHookCallBack != null)
            {
                OnHookCallback(trueKeyPressed);
            }
        }
        return CallNextHookEx(_hookID, nCode, wParam, lParam);
    }
}

Guess what? 你猜怎么了? Now your HookCallBack method doesn't even need to know of the existence of forms. 现在,您的HookCallBack方法甚至不需要知道表单的存在。 Instead, your forms register themselves to the event handler as such: 相反,您的表单将自己注册到事件处理程序中,如下所示:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        MessageHooks.OnHookCallBack += MessageHooks_OnHookCallBack;
        this.FormClosed += (sender, e) => MessageHooks.OnHookCallBack -= MessageHooks_OnHookCallBack; // <--- ALWAYS UNHOOK ON FORM CLOSE
    }

    void MessageHooks_OnHookCallBack(int keyPressed)
    {
        // do something with the keypress
    }
}

Remember, you must unhook your forms event handler on form close, otherwise the form won't get garbage collected, and you'll run into lots of weird issues raising events on non-visible forms. 请记住,您必须在窗体关闭时解开窗体事件处理程序,否则窗体将不会被垃圾收集,并且您会遇到很多奇怪的问题,从而在不可见的窗体上引发事件。

From what you've written, I think this will work: 从您写的内容来看,我认为这将起作用:

In Form1 , have a static member of type Form1 which will hold the instance : Form1 ,具有一个Form1类型的静态成员,该成员将保存实例:

private static Form1 instance;

In the Form1 constructor, set this static member to the instance being created: Form1构造函数中,将此静态成员设置为正在创建的实例:

public Form1()
{
    // Existing code

    Form1.instance = this;
}

Now, make newKeyPress static, and use the static member to find the actual form instance: 现在,将newKeyPress静态,并使用静态成员查找实际的表单实例:

public static void newKeyPress(int trueKeyPressed)
{
    Form1 thisIsTheForm1Instance = Form1.instance;

    // Now instance.form1string is the data you want
}

I think something like having in the Form1 class: 我认为就像在Form1类中一样:

private static Form1 instance;


 public static Form1 Instance
 {
      get
      {
          if (instance == null)
          {
              instance = new Form1();
          }
          return instance;
      }
 }

And in your classes which use them: 在使用它们的类中:

Form1 form1 = Form1.Instance;

Will do the job. 会做的工作。 This will first check if there is one, if so it will return the instance else it will create one and next time it will return one. 这将首先检查是否存在一个,如果是,它将返回该实例,否则将创建一个,然后再次返回一个。

暂无
暂无

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

相关问题 如果我只有类的字符串名称,该如何在静态类上调用方法? - How do I call a method on a static class if I've only got the classes string name? 如何从静态方法访问类的实例? - How do I access an instance of a class from a static method? 实例方法的'this'参数可以是无类型的(即System.Object)吗? - Can 'this' argument of an instance method be untyped (i.e. System.Object)? 如何确保类可以在另一个类上调用方法,但其他类不能调用该方法? - How do I ensure a Class can call a method on another Class, but not other Classes can call that method? 为什么在除数(/)之前执行方法调用(即ToString)? - Why method call (i.e. ToString) executed before divisision ( / )? 如何调用仅接受另一种形式的参数的方法? - How do I call a method that only accepts a parameter that is in another form? 如何从其他类的静态方法中调用非静态方法? - How do I call a non-static method from a static method from a different class? 如何在另一个脚本中调用对象的“移动”方法? 统一 - How do I call the “Movement” method of an object in another script? Unity C#如何在不使方法静态的情况下从界面内的另一个类调用方法? - C# How do I call a method from another class inside of my interface without making the method static? C#:如何从派生类的静态方法调用基类的静态方法? - C#: How do I call a static method of a base class from a static method of a derived class?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM