Skip to content

Instantly share code, notes, and snippets.

@RhysC
Created January 5, 2016 08:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RhysC/ca18af47a9f4926d8ab5 to your computer and use it in GitHub Desktop.
Save RhysC/ca18af47a9f4926d8ab5 to your computer and use it in GitHub Desktop.
Execute/Dispatch/Call all available methods on the object that can handle the parameter
void Main()
{
new MyObject().Dispatch(new Bar());
/* OUTPUT:
Easy more specific target
Hitting the Bar
Fooing it up
Easy target
*/
}
// Define other methods and classes here
public class MyObject
{
private void Handle(object x)
{
"Easy target".Dump();
}
private void Handle(IFoo theInterface)
{
"Easy more specific target".Dump();
}
private void Handle(Foo foo)
{
"Fooing it up".Dump();
}
private void Handle(Bar bar)
{
"Hitting the Bar".Dump();
}
private void Handle(Foo foo, Bar bar)
{
throw new Exception("I should not be hit, do not have a single parameter");
}
private void Handle(string theString)
{
throw new Exception("I should not be hit, my parameter is of the wrong type");
}
}
public interface IFoo { }
public class Foo : IFoo { }
public class Bar : Foo { }
public static class DispatcherEx
{
//Will execute all methods that are called "Handle" take a sinlge parameter that can be considered T
public static void Dispatch<T>(this object self, T parameter)
{
var handlers = self.GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)
.Where(m => m.Name == "Handle" && m.GetParameters().Count() == 1)
.ToDictionary(m => m.GetParameters().Single().ParameterType,
m => (Action<T>)(e => m.Invoke(self, new object[] { e })));
// Dispatch to all matching methods (not just most-specific)
var paramType = parameter.GetType();
var suitableTypes = paramType.GetInterfaces().Concat(GetBaseClasses(paramType));
foreach (var suitableType in suitableTypes.Where(suitableType => handlers.ContainsKey(suitableType)))
{
handlers[suitableType](parameter);
}
}
private static IEnumerable<Type> GetBaseClasses(Type type)
{
for (var current = type; current != null; current = current.BaseType)
yield return current;
}
}
@RhysC
Copy link
Author

RhysC commented Mar 9, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment