在调用多播代理时,应该使用GetInvocationList逐个调用代理:
public void IterateAll()
{
if( _doExecute != null )
{
foreach( ExecuteCallback doSingleExecute in _doExecute.GetInvocationList() )
{
try
{
doSingleExecute();
}
catch
{
// This delegate threw an exception
}
}
}
}有没有一种方法可以泛化这一点,通过包装这个迭代来返回到一个单一的调用,从而隐藏它,并且使得一个人可以再次调用整个多播委托?这将更接近意向水平。
发布于 2010-11-12 06:59:21
你可以这样做:
public static void CallAllAndCatch(this Action self)
{
if (self == null)
return;
foreach (Action i in self.GetInvocationList()) {
try { i(); }
catch { }
}
}请注意,如果你发现自己经常使用EventHandler<T>来做这件事,你可以使用泛型,但是你不能对任何类型的委托通用地这样做,因为委托类型不能在彼此之间分配,即使它们是兼容的,并且在定义泛型方法时没有机制来限制特定的泛型参数成为具有特定签名的委托。(我认为从.NET 4开始,具有相同签名的委托被认为是兼容的类型。)
对于EventHandler<T>方法:
public static void CallAllAndCatch(this EventHandler<T> self, object sender, T args)
where T : EventArgs
{
if (self == null)
return;
foreach (EventHandler<T> i in self.GetInvocationList()) {
try { i(sender, args); }
catch { }
}
}如果你不介意抛出性能和编译时类型检查,你可以这样做,这将适用于任何委托类型:
public static void CallAllAndCatch(this Delegate self, params object[] args)
where T : EventArgs
{
if (self == null)
return;
foreach (Delegate i in self.GetInvocationList()) {
try { i.DynamicInvoke(args); }
catch (MemberAccessException) { throw; } // A type of something in args isn't compatible with the delegate signature.
catch (TargetException) { throw; } // The delegate itself is invalid.
catch { } // Catch everything else.
}
}发布于 2010-11-12 07:34:57
Hmya,这很可疑。只有当您能够恢复程序的状态时,捕获异常并处理它才能真正起作用,这样看起来就像从未发生过异常一样。对于MulticastDelegate来说,这是完全不可能的。
它的约定是你不知道什么样的代码为它订阅了一个事件处理程序。如果完全未知代码抛出异常且不处理自身,那么您根本无法猜测如何恢复状态。事件处理程序可能已经完成了一系列工作,改变了状态,然后在接近尾声的地方死了。你没有希望取消“一堆工作”的部分,代码对你来说是未知的。它可能是在您编写代码的几个月或几年后编写的。
真不是个好主意,不要这样做。
发布于 2010-11-12 07:03:17
委托的类型是固定的吗?你要么需要使用相当多的反射,要么需要为每个可能的参数计数实现一个版本,就像它有一个Action<...>类型一样。
应该看起来像这样(未测试的记事本代码):
public static Action WrapAction(Action a)
{
var invList = ((MultiCastDelegate)a).GetInvocationList();
for (int i = 0; i < invList.Length; i++)
{
invList[i] = ()=>{try invList[i] catch {...} });
}
return (Action)MulticastDelegate.Combine(invList);
}而且您可能需要为单类型转换委托添加特殊的情况处理。
https://stackoverflow.com/questions/4160031
复制相似问题