更改事件的顺序
本文关键字:顺序 事件 | 更新日期: 2023-09-27 18:32:00
我有一个控件(按钮),其中包含一个包含文本"Test A"的消息框,并添加了一个带有另一条消息"Test B"的委托。下面的代码首先显示消息"测试 A",然后显示"测试 B":
c.Click += delegate(object sender, EventArgs e)
{
MessageBox.Show("Test B");
};
我需要类似于我所做的代码的东西,但无法正常工作:
EventHandler handler;
c.click -= handler;
handler = delegate(Object sender, EventArgs e)
{
MessageBox.Show("Test B");
};
c.Click += handler;
我需要更改顺序,即显示消息"测试 B",然后显示"测试 A"。可能吗?
您可以取消注册并重新注册:
button1.Click -= button1_Click; // unregister main event
button1.Click += delegate(object sender, EventArgs e) // reigster new one
{
MessageBox.Show("Test B");
};
button1.Click += button1_Click; // register again old
按钮单击事件:
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("Test A");
}
现在它将首先调用调用测试 B,然后调用测试 A
您提到您的程序包含某种编译器,并且用户可以指定其代码是在现有代码之前还是之后运行。在我看来,您可以简单地在您自己的事件处理程序中处理用户代码,该处理程序按所需的顺序运行您和用户的代码(正如 Nikola 已经提到的)。
换句话说,不要直接向用户代码公开这些事件,而是使用您自己的事件处理程序"包装"它们。从用户的角度来看,没有任何变化 - 他们仍然认为他们可以直接访问事件。但是您可以控制如何处理用户代码,因此您可以自由地在两者之间插入一个层,以确保正确的执行顺序:
c.Click += (sender, e) =>
{
if (hasUserEventHandler && runUserEventHandlerFirst)
UserEventHandler(sender, e);
StandardEventHandler(sender, e);
if (hasUserEventHandler && !runUserEventHandlerFirst)
UserEventHandler(sender, e);
};
我的意思是,你可以做这样的事情:
public void SwapDelegateOrder(object obj, string eventName)
{
// Fetch the underlying event handler field (let's *assume* it has the same name):
var delegateField = obj.GetType().GetField(eventName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
var mcDelegate = delegateField.GetValue(obj) as MulticastDelegate;
if (mcDelegate == null)
return;
// Get the add and remove methods:
var evt = obj.GetType().GetEvent(eventName);
var add = evt.GetAddMethod(true);
var remove = evt.GetRemoveMethod(true);
// Remove all invocations...
var invocations = mcDelegate.GetInvocationList();
foreach (var invocation in invocations)
remove.Invoke(obj, new object[] { invocation });
// ...and add them back in, in reverse order (*assuming* that invocations are called in the order they're added):
foreach (var invocation in invocations.Reverse())
add.Invoke(obj, new object[] { invocation });
}
但这是基于有关编译器和运行时实现(事件字段名称和执行顺序)的假设。如果在编译器更新或下一个 .NET 框架版本中更改了其中一些详细信息,该怎么办?你无法控制它,但你可以控制自己的代码。