[.net] Dynamic type-casting

Started by
11 comments, last by qingrui 15 years, 10 months ago
Quote:Original post by capn_midnight

That only works if he has explict references to the EventArg types. If he is writing an event dispatching system that only ever handles argument sub-types through handles of the base EventArg type, then attempting to make a call like that will result in an ambiguous reference compile time error. The visitor pattern is necessary here.


This is the problem which I am encountering; I am using an interface IEventData, for example, to store event arguments. If I am using delegates (which is what .NET EventHandler boils down to, I believe), the signature would look like this:

public delegate bool EventHandler(IEventData eventData);


I would like to new event types to added (I am writing a close-source game library as part of the job description), so the coupling of events to their handlers has to be super-loose -- preferably, the user adding a new event type does not requires him to recompile the game library while at the same time, the library is supposed to have several pre-defined events.

Hence this topic.

Thanks a lot for code snippets so far, but how likely is the performance hit with reflection?

(BTW, don't worry about simple code fragments -- I am new to this reflection, where in C++ where RTTI is considered as the greatest sin in OOP or something, so simple code helps too :) )

GamesTopica.Net- http://www.gamestopica.net
Advertisement
@ OP: Wow, that code you found is horrible :D!

benryves' observation about function overloading is the best to solve this particular example, since the caller is not calling using a base class reference.

The "as" keyword is much better than comparing type names if you DO get stuck with a caller-side base class reference.

Interfaces and (to a certain extent) extension methods can provide slightly different and possibly more powerful ways of getting things like this done with fewer lines of code than the Visitor example.
Reflection and MethodInfo.Invoke() are very slow compared to normal function calls. Actually MethodInfo.Invoke() is used by VB.NET to implement dynamic binding. So the it may actually perform worse than if-else.

The right solution is to use Dictionary and delegates. Delegates are about the same speed as interface method calls. And to allow casting to derived event data types, generic and a wrapper class are needed. It is roughly like this:

class Dispatcher
{
Dictionary<Type, HandlerBase> dict;
public void Register<T>(Action<T> handler) where T: EventData
{
dict.Add(typeof(T), new Handler<T>(handler));
}
public void Dispatch(EventData data)
{
dict[data.GetType()].Invoke(data);
}
abstract class HandlerBase
{
public abstract void Invoke(EventData data);
}
class Handler<T> : HandlerBase where T: EventData
{
Action<T> handler;
public override void Invoke(EventData data)
{
handler((T)data);
}
}
}

This topic is closed to new replies.

Advertisement