如果我有这样的代表:
Delegate void Render();
Render ToRender;
在这里使用它:
ToRender += FunctionRender;
ToRender += SomeOtherRender;
如何制作它以便我可以单独调用每个功能?像这样:
foreach(Render render in ToRender)
{
BeginRender();
render();
EndRender();
}
答案 0 :(得分:11)
您可以使用Delegate.GetInvocationList()
分别获取每个。
foreach (Render render in ToRender.GetInvocationList())
{
...
}
请注意,GetInvocationList()
只会返回Delegate[]
,但foreach
会对每个项目进行隐式转换,这就是上述循环的工作原理。
哦,你应该首先检查ToRender
是否null
,否则你将获得NullReferenceException
。你实际上可以编写一个通用的扩展方法来使这个更好,但是你需要对C#中不允许的委托类型有一个约束:(
如果你不关心缺乏约束,你可以伪造它:
public static IEnumerable<T> GetIndividualDelegates<T>(this T multiDelegate)
where T : class
{
if (multiDelegate == null)
{
yield break;
}
Delegate d = (Delegate)(object) multiDelegate;
foreach (Delegate item in d.GetInvocationList())
{
yield return (T)(object) item;
}
}
(由于对通用转换的限制,这很尴尬。)
你可以这样写:
foreach (Render render in ToRender.GetIndividualDelegates())
{
...
}
不用担心ToRender
是否为空。
答案 1 :(得分:3)
foreach (Render render in ToRender.GetInvocationList())
Render temp = ToRender;
if (temp != null)
{
foreach (Render render in temp.GetInvocationList())
{
BeginRender();
render();
EndRender();
}
}
答案 2 :(得分:1)
ToRender.GetInvocationList返回“list”中包含的所有委托的数组。
答案 3 :(得分:-1)
这不是委托和事件的工作方式。框架将自动调用所有方法。事件处理程序应该能够完全独立于任何其他处理程序执行。如果你需要更紧密地控制流量,你应该考虑重新设计你的方法。
也许是3个事件/代表 - 类似于asp.net的方式。 PreRender,Render和PostRender。我不确定你在做什么,但这听起来有点矫枉过正。只是以为我会扔掉它。