Calling delegates individually?

2019-03-29 20:32发布

问题:

if I have a delegate like so:

 Delegate void Render();
 Render ToRender;

And use it here:

 ToRender += FunctionRender;
 ToRender += SomeOtherRender;

How can I make it so I can invoke each function seperately? Something like this:

 foreach(Render render in ToRender)
 {
     BeginRender();


     render();


     EndRender();
 }

回答1:

You can fetch each one separately using Delegate.GetInvocationList().

foreach (Render render in ToRender.GetInvocationList())
{
    ...
}

Note that GetInvocationList() just returns a Delegate[], but foreach has an implicit cast on each item, which is what makes the above loop work.

Oh, and you should check whether ToRender is null or not first, of course - otherwise you'll get a NullReferenceException. You could actually write a generic extension method to make this nicer, but you'd need a constraint on the delegate type which isn't allowed in C# :(

If you don't care about the lack of constraints, you could fake it:

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;
    }    
}

(It's awkward because of the restrictions on generic conversions.)

That way you could write:

foreach (Render render in ToRender.GetIndividualDelegates())
{
    ...
}

without worrying about whether ToRender was null or not.



回答2:

foreach (Render render in ToRender.GetInvocationList())

Ideal Way:

Render temp = ToRender;

if (temp != null)
{
    foreach (Render render in temp.GetInvocationList())
    {
        BeginRender();

        render();

        EndRender();
    }
}


回答3:

ToRender.GetInvocationList returns an array of all delegates contained on the "list".



回答4:

thats not how delegates and events work. all methods will automatically be invoked by the framework. event handlers should be able to be executed completely independent of any other handlers. if you need to control the flow more tightly, you should think about redesigning your approach.

perhaps 3 events/delegates - similar to the way asp.net does it. PreRender, Render and PostRender. im not sure what you are doing, but this sounds like overkill to me. just thought i would throw it out.



标签: c# delegates