我有一个控件(按钮),其中包含一个消息框,其中包含文本"测试A"并添加了一个代表与另一个消息"测试B"。下面的代码首先显示了#34;测试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"。有可能吗?
答案 0 :(得分:3)
您可以取消注册并重新注册:
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");
}
现在它将首先调用Call 测试B ,然后再调用测试A
答案 1 :(得分:2)
您提到您的程序包含某种类型的编译器,并且用户可以指定其代码是在现有代码之前还是之后运行。在我看来,您可以简单地处理您自己的事件处理程序中的用户代码,该处理程序以所需的顺序运行您的和用户代码(正如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框架版本中更改了其中一些细节,该怎么办?您无法控制,但您可以控制自己的代码。