using System.Collections.Generic;
public interface IAction {}
public interface IAction<T> : IAction
public abstract class Base
public string Name{ get; set; }
public class Foo : Base {}
public class FooAction : IAction<Foo>
public string Do(Foo f) { return "Got Foo: " + f.Name; }
public class Qux : Base {}
public class QuxAction : IAction<Qux>
public string Do(Qux q) { return "Got Qux: " + q.Name; }
public enum Bar { X, Y, Z }
public class BarAction : IAction<Bar>
public string Do(Bar b) { return "Got Bar value: " + b; }
Dictionary<Type, IAction> m_actions = new Dictionary<Type, IAction>();
public void Register<T>(IAction<T> action)
m_actions.Add(typeof(T), action);
public string Get(object t)
var action = m_actions[t.GetType()];
return ((dynamic)action).Do((dynamic)t);
public static void Main()
Base foo = new Foo{ Name = "Baz" };
Base qux = new Qux{ Name = "Qaz" };
var fooAction = new FooAction();
var quxAction = new QuxAction();
var barAction = new BarAction();
var program = new Program();
program.Register<Foo>(fooAction);
program.Register<Bar>(barAction);
program.Register<Qux>(quxAction);
Console.WriteLine(program.Get(foo));
Console.WriteLine(program.Get(qux));
Console.WriteLine(program.Get(bar));