It sounds like you're expecting overload resolution to occur at execution time. That doesn't happen... unless you use dynamic
, which may well be the simplest solution for you:
dynamic order = GetOrder(orderId);
HandleOrder(order); // The right overload will be picked at execution time
Another alternative would be to use double-dispatch / the visitor pattern, but personally I find that a bit clunky.
Another alternative would be to make a Dictionary<Type, Action<Order>>
like this:
private static readonly Dictionary<Type, Action<Order>> orderHandlers =
new Dictionary<Type, Action<Order>>
{
{ typeof(OrderA), order => HandleOrder((OrderA) order) },
{ typeof(OrderB), order => HandleOrder((OrderB) order) },
{ typeof(OrderC), order => HandleOrder((OrderC) order) },
{ typeof(OrderD), order => HandleOrder((OrderD) order) },
};
Then just fetch the relevant delegate and call it:
orderHandlers[order.GetType()](order);