Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/url/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
有没有办法通过C#中的Type.InvokeMember或messages调用窗体或类的私有函数?_C#_Messaging_Invoke_Private Methods - Fatal编程技术网

有没有办法通过C#中的Type.InvokeMember或messages调用窗体或类的私有函数?

有没有办法通过C#中的Type.InvokeMember或messages调用窗体或类的私有函数?,c#,messaging,invoke,private-methods,C#,Messaging,Invoke,Private Methods,我的主要应用程序中有一堆表单,它们同时具有私有和公共功能。我有一个插件体系结构,在创建和加载表单时可以访问每个表单,并保存对表单的引用,用于更新表单、添加控件等 我们正在尝试实现这个插件架构,但是一些插件可能需要调用表单的私有函数。下面是我尝试使用Type.InvokeMember的示例: public partial class Form1 : Form { Form1() { InitializeComponent(); } private

我的主要应用程序中有一堆表单,它们同时具有私有和公共功能。我有一个插件体系结构,在创建和加载表单时可以访问每个表单,并保存对表单的引用,用于更新表单、添加控件等

我们正在尝试实现这个插件架构,但是一些插件可能需要调用表单的私有函数。下面是我尝试使用Type.InvokeMember的示例:

public partial class Form1 : Form
{
    Form1()
    {
        InitializeComponent();
    }

    private void SayHello()
    {
        MessageBox.Show("Hello World!");
    }
}
在另一个DLL中

public class PluginClass
{
    Form1 myReferencedForm1;

    PluginClass()
    {
        //Constructor code here...

        //Also sets the reference to existing Form1 instance
    }

    private CallMember()
    {
        Type t = typeof(Form1); //I guess I can also call 'myReferencedForm1.GetType();' here as well
        t.InvokeMember("SayHello",
                       System.Reflection.BindingFlags.InvokeMethod |
                       System.Reflection.BindingFlags.NonPublic |
                       System.Reflection.BindingFlags.Public,
                       null, myReferencedForm1, new object[] { });
    }
}
我尝试了
“SayHello”
“SayHello()”
,它们都返回了“MissingMethodException”错误:

Method 'Form1.SayHello()' not found.

我需要创建和使用活页夹吗?如果是,我该怎么做?使用System.Windows.Forms.Message可以更轻松地完成此操作吗?如果是这样的话,怎么办?

您忘记将
BindingFlags.Instance
添加到标志列表中:

t.InvokeMember("SayHello", 
               BindingFlags.Intance |
                   BindingFlags.InvokeMethod |
                   BindingFlags.NonPublic,
               null, 
               myReferencedForm1,
               new object[] { });
但是,老实说,我更喜欢先获取该方法,然后使用返回的MethodInfo对象调用该方法:

if(myReferencedForm1 != null)
{
    var type = typeof(Form1);
    var method = type.GetMethod("SayHello", BindingFlags.Instance
        | BindingFlags.NonPublic);

    method.Invoke(myReferencedForm1);
}

您尚未在标记列表中包含BindingFlags.Instance。。。所以它既没有实例也没有静态方法要检查

就我个人而言,我通常先调用
GetMethod
,然后调用
MethodInfo.Invoke
,将方法的发现与调用分开。我发现这使得调试更容易,但是YMMV

完整样本:

using System;
using System.Reflection;

class OtherClass
{
    private void Foo()
    {
        Console.WriteLine("OtherClass.Foo");
    }
}

class Test
{
    static void Main()
    {
        OtherClass target = new OtherClass();
        typeof(OtherClass).InvokeMember("Foo",
            BindingFlags.InvokeMethod | BindingFlags.Instance |
            BindingFlags.Public | BindingFlags.NonPublic,
            null, target, new object[0]);
    }
}
或者使用我的“从调用中分离提取”:


invokeAttr
参数应为

BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.NonPublic
别那么做

使用
DoMethod(字符串名称)
成员创建一个接口:
IPluginHost
。为每个表单实现该接口,您甚至可以使用
partial class
声明将其提取到另一个文件中

在方法impl中,做简单的切换用例来踢合适的方法。使用一些脚本来生成它

public interface IPluginHost
{
    void DoMethod(string MethodName);
}

public partial MyForm:Form, IPluginHost
{
    #region IPluginHost implementation
    public void DoMethod(string MethodName)
    {
         switch (MethodName)
             case "SayHello":
                 SayHello();
                 break;
             ...
    }
    #endregion
}

如果你正在做架构,不要一开始就修改它。

将你的BindingFlags更改为

private CallMember()
{
    Type t = typeof(Form1); //I guess I can also call 'myReferencedForm1.GetType();
    t.InvokeMember("SayHello",
                   System.Reflection.BindingFlags.InvokeMethod |
                   System.Reflection.BindingFlags.Instance |
                   System.Reflection.BindingFlags.NonPublic,
                   null, myReferencedForm1, new object[] { });
}

这应该可以做到这一点。

这是它们的副本,它们在同一个dll中吗?你可以将SayHello()设置为内部的,而不是私有的,如果soNo不是。我会更新问题中的代码。我应该更清楚。。。我比不上乔恩·斯基特+1我不得不同意,既然有这样一种更容易/更干净的方法,为什么还要走艰难/肮脏的道路呢。
private CallMember()
{
    Type t = typeof(Form1); //I guess I can also call 'myReferencedForm1.GetType();
    t.InvokeMember("SayHello",
                   System.Reflection.BindingFlags.InvokeMethod |
                   System.Reflection.BindingFlags.Instance |
                   System.Reflection.BindingFlags.NonPublic,
                   null, myReferencedForm1, new object[] { });
}