views:

837

answers:

4

I have an interface method

  public void Execute(ICommand command);

which needs to pass known subtypes of ICommand to an apropriate Handle(SpecificCommand command) method implementation and do some generic handling of unknown types. I am looking for a universal (i.e. not requiring a giant switch) method of doing so, something similar to

  Handle(command as command.GetType()); // this obviously does not compile

I know I could register the handlers somehow, e.g. store them as delegates in a dictionary, but this still requires duplicating the handling logic (once in the specific Handle(...) method signature, once in the delegate reqistration). If I populate the dictionary by inspecting my class with reflection (looking for Handle(XXX command) methods), I'll get a performance hit.

To summarize: how can I downcast an object (upcasted by the call to Execute(ICommand command)) to invoke a method requiring a concrete type without knowing which type it is at compile time.

+2  A: 

You can't, and why would you want to?

That's the whole reason we have polymorphism. If you want to have custom behaviour that is specific to certain types, then the behaviour should live in the type itself and be invoked via a function declared in the base class type.

OJ
My problem is that I want custom behaviour, specific not only to a certain type, but also specific to a consumer of this type.
skolima
+9  A: 

Well, the "correct" answer is that Handle() should be a method in ICommand, so that instead of Handle(command), you'd be saying command.Handle().

James Curran
Problem is that Execute() is an interface method, various implementors will handle the commands differently. And I would prefer not to add methods to the interface each time I add a command, as this breaks implementors each time.
skolima
@skolima I think you need to be more specific, I agree with James' criticism, almost certainly you want to use polymorphism here rather than some horribly kludgey switch statement or some such. Encapsulate code where it belongs.
Wedge
The Execute() method and various ICommand classes are part of my API. I provide a single implementation of Execute(), but clients will provide others. I want the clients to be able to still compile correctly when I add new commands (An UnknownCommand response is possible).
skolima
@skolima if you haven't finalized your design yet then you have time to change your API. Don't lock yourself into a bad decision just because you don't think there are alternatives.
Wedge
+5  A: 

The cast is emitted at compile-time, so you need to know the type at compile-time. The overloading is also determined at compile-time - so by the time you actually know the concrete type to use, it's too late.

I don't see that you'd actually be duplicating any logic by using delegates. Alternatively, if you do it with reflection, you can build delegates very easily using Delegate.CreateDelegate - you'll only get a performance hit once, and after that it'll be very fast. See my blog entry about Delegate.CreateDelegate for more information.

I think I'd decide to use a hand-built dictionary or one built with reflection based on how many methods I had and how often they change. You'll probably find KeyedByTypeCollection useful for the dictionary.

Jon Skeet
I have read your article before - very useful!
skolima
+1  A: 

I've tried working out a way which would work using Double Dispatch (http://en.wikipedia.org/wiki/Double_dispatch), but it seems that you have a situation where the number of classes implementing ICommand and those implementing Execute() can vary at run-time (or, at least between compile & run-time, which is essentially the same thing), so the only solution I can see it use the dictionary as Jon Skeet propsed.

James Curran