gpt4 book ai didi

c# - 如何通过反射获取事件目标方法

转载 作者:行者123 更新时间:2023-11-30 23:24:23 26 4
gpt4 key购买 nike

我有一个非常简单的类:

public delegate void ChangedEventHandler_OUT();
public class Plugin
{

public Plugin(string _pluginName)
{
pluginName = _pluginName;
}

public string pluginName;
public string member1;
public string member2;

public event ChangedEventHandler_OUT OnStatusChange1_OUT;
public event ChangedEventHandler_OUT OnStatusChange2_OUT;

public void PluginAction()
{
MessageBox.Show("ACtion from plugin " + pluginName);
}

}

在 Main 中,我创建了两个实例并连接它们的事件:

var plugin1 = new Plugin("plugin1") { member1 = "AAA1", member2="BBB1"};
var plugin2 = new Plugin("plugin2") { member1 = "AAA1", member2 = "BBB1" };

plugin1.OnStatusChange1_OUT += plugin2.PluginAction;

现在我完全意识到这没有什么意义,但我想深入反射(reflection)并获得我能获得的所有信息:

MEMBERS

lbxInfo.Items.Add("Plugin1 member:");
Type type = typeof(Plugin);
foreach (var field in type.GetFields())
{
string strName = field.Name; // Get string name
string strType = field.FieldType.Name;
string strValue = (string)field.GetValue(plugin1);
lbxInfo.Items.Add(strType + " " + strName + " = " + strValue);
}

这很好用 enter image description here

现在我想获取有关事件的所有信息:

EVENTS:

lbxInfo.Items.Add("Plugin1 events:");
foreach (var ev in plugin1.GetType().GetEvents())
{
string strName = ev.Name;
string strType = ev.EventHandlerType.Name;
MethodInfo strConnectedTo = ev.GetAddMethod();

lbxInfo.Items.Add("Name = " + strName + " type =" + strType);

}

enter image description here

我没能做到的部分是理解什么事件与什么有关。简而言之,我想添加一个部分,告诉我哪些事件与哪些事件相关联,哪些不相关。像这样的东西:

Plugin1 OnStatusChange1_Out connectedTo plugin2.PluginAction OnStatusChange1_Out connectedTo NULL

这显然必须通过反射并在上面的同一个 foreach 循环中完成。

提前感谢您的帮助帕特里克


为 Jeroen van Langen 添加:

你写的有用。我试图将建议的解决方案放入反射循环中:

public void CheckEventInfo(Plugin plg, ChangedEventHandler_OUT ev)
{
string invocationList = null;
if (ev != null)
foreach (var item in ev.GetInvocationList())
invocationList += item.Method.Name;
}

然后

        lbxInfo.Items.Add("Plugin1 events:");
foreach (var ev in plugin1.GetType().GetEvents())
{
string strName = ev.Name;
string strType = ev.EventHandlerType.Name;
MethodInfo strConnectedTo = ev.GetAddMethod();

CheckEventInfo( plugin1,ev);<------NO!
lbxInfo.Items.Add("Name = " + strName + " type =" + strType);
}

所以在这里我不知道该放什么,因为 ev 是一个事件信息而不是 ChangedEventHandler_OUT。请你帮助我好吗?谢谢

最佳答案

我想您只是出于教育目的而这样做。一般来说,如果您想知道某个特定事件是否有任何订阅者,或者更糟的是,想知道订阅者的确切列表,那么您就犯了架构错误。 (事件调用方法存在一个异常(exception),它应该在调用之前检查事件委托(delegate)是否为空。)

这是获得所需结果的方法。

string GetSubscriptions(object o)
{
Type t = o.GetType();

// Obtain the collection of EventInfo's
var events = t.GetEvents();
if (events.Length == 0)
{
return "No events in " + t.Name;
}

string result = string.Empty;
foreach (var item in events)
{
result += "Event " + item.Name + ": ";

// Get the event's backing field description (FieldInfo)
var ed = t.GetField(item.Name, BindingFlags.Instance | BindingFlags.NonPublic);
if (ed == null)
{
throw new InvalidOperationException("Event backing field could not be obtained");
}

// Get the value of the backing field
var dl = ed.GetValue(o) as Delegate;

// If value is not null, then we've subscriptions
if (dl != null)
{
// Get the invocation list - an array of Delegate
var il = dl.GetInvocationList();

// This check is actually not needed, since the array should always contain at least 1 item
if (il.Length != 0)
{
// Use Target property of the delegate to get a reference to the object the delegate's method belongs to
result += string.Join("; ", il.Select(i => i.Target.GetType().Name + "." + i.Method.Name)) + Environment.NewLine;
continue;
}
}

result += "no subscriptions" + Environment.NewLine;
}

return result;
}

您必须记住,对于静态事件,Target 属性可以为 null。要也获取静态事件,请将 BindingFlags.Static 包含到 GetField() 方法的第二个参数中。

关于c# - 如何通过反射获取事件目标方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37831513/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com