我给元素添加了一个eventandler:
element.AddHandler(Class.Event, handler, true);
但是没有调用处理程序方法。如何验证处理程序是否已正确添加?比如:
element.GetAssociatedHandlers();
谢谢!
如果只想在调试器中验证是否添加了事件处理程序,可以将事件强制转换为System.Delegate
并查看调用列表。这可以在Visual Studio即时窗口中实现。这里我正在检查一个名为"MyEvent"的事件的调用列表,结果发现它添加了3个处理程序:
((System.Delegate)MyEvent).GetInvocationList()
{System.Delegate[3]}
[0]: {Method = {Void handler11_MessageReceived(System.Object, MyProject.MyEventArgs)}}
[1]: {Method = {Void handler21_MessageReceived(System.Object, MyProject.MyEventArgs)}}
[2]: {Method = {Void handler21_MessageReceived(System.Object, MyProject.MyEventArgs)}}
您也可以在"监视"窗口中浏览调用列表。
如果您不确定稍后是否正确处理了某些事件侦听器,那么这样做甚至可能很有用,例如
Update:如何以编程方式检查一个事件是否包含另一个事件。
以编程方式检查事件处理程序是否已添加到事件中比人们想象的要复杂,因为事件实际上是MulticastDelegate的一种形式。多播委托可以是由(例如)委托语句或lambda表达式创建的"原子"删除,也可以是通过将两个或多个多播委托加在一起创建的组合委托。结果是,当一个组合委托被添加到或从另一个组合委托中减去时,实际发生的是它的调用列表被添加到或从另一个组合委托中减去。例如
Action a = () => Console.WriteLine("a");
Action b = () => Console.WriteLine("b");
Action c = () => Console.WriteLine("c");
Action d = () => Console.WriteLine("d");
var ab = a + b;
var cd = c + d;
var ad = a + d;
var bc = b + c;
var abcd = ab + cd;
var adbc = ad + bc;
var abc = abcd - d;
var bcd = abcd - a;
bool test1 = (abcd == (a + b + c + d)); // returns true
bool test2 = abcd.GetInvocationList().Contains(a); // returns true;
bool test3 = abcd.GetInvocationList().Contains(ab); // returns **false**;
bool test4 = abc.GetInvocationList().Contains(d); // returns false
如果你想创建一个公共静态扩展方法来检查你的处理程序是否被添加到一个事件,它应该正确地处理一个多播委托被添加的情况。但是,这仅仅意味着事件拥有处理程序的所有委托吗?或者它们是否需要按顺序绑定在一起,因为Delegate。联合保存秩序?下面的扩展方法检查后者:
public static class EventHelper
{
/// <summary>
/// Return true if all the atomic delegates in the multicast delegate handler are bound into the
/// publisher, grouped together and in the same order.
/// </summary>
/// <param name="publisher"></param>
/// <param name="handler"></param>
/// <returns></returns>
public static bool HasBound(this Delegate publisher, Delegate handler)
{
if (publisher == null || handler == null)
return false;
if (publisher == handler)
return true;
var publisherList = publisher.GetInvocationList();
var handlerList = handler.GetInvocationList();
return (publisherList.SublistIndex(handlerList, 0) >= 0);
}
public static bool HasBound<TEventArgs>(this EventHandler<TEventArgs> publisher, EventHandler<TEventArgs> handler) where TEventArgs : EventArgs
{
return HasBound((Delegate)publisher, (Delegate)handler);
}
public static bool HasBound(this EventHandler publisher, EventHandler handler)
{
return HasBound((Delegate)publisher, (Delegate)handler);
}
}
public static class ListHelper
{
public static int SublistIndex<T>(this IList<T> list, IList<T> sublist, int start)
{
var comparer = EqualityComparer<T>.Default;
for (int listIndex = start, end = list.Count - sublist.Count + 1; listIndex < end; listIndex++)
{
int count = 0;
while (count < sublist.Count && comparer.Equals(sublist[count], list[listIndex + count]))
count++;
if (count == sublist.Count)
return listIndex;
}
return -1;
}
}
测试结果如下:
bool test08 = a.HasBound(a); // returns true;
bool test09 = b.HasBound(a); // returns true;
bool test10 = abcd.HasBound(a + b + c + d); // returns true;
bool test11 = abcd.HasBound(adbc); // returns false - wrong order.
bool test12 = abcd.HasBound(a); // returns true;
bool test13 = cd.HasBound(a); // return false
bool test14 = bcd.HasBound(bc); // returns true despite the fact that bcd was not created directly from bc.
bool test15 = abcd.HasBound(ad); // returns false because the "ad" events are not adjacent in abcd.
老实说,我不会在调试之外这样做。实际上编写检查来查看侦听器是否绑定到事件似乎是错误的。
更新2是真正的问题在这里如何获取所有的事件处理程序从微软的UIElement?它必须通过一些讨厌的反射来完成,这些反射不能保证在未来的。net版本中工作,如下所示:和这里:如何可能删除'Click'
您可以获取委托的调用列表来验证您的处理程序是否附加。
event Action MyEvent;
bool IsEventHandlerAdded()
{
foreach (Delegate existingHandler in this.MyEvent.GetInvocationList())
{
return existingHandler == MyEvent;
}
return false;
}