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