Skip to content

Instantly share code, notes, and snippets.

@sean-gilliam
Created November 6, 2014 15:50
Show Gist options
  • Save sean-gilliam/db65ec4152c1ed8615d3 to your computer and use it in GitHub Desktop.
Save sean-gilliam/db65ec4152c1ed8615d3 to your computer and use it in GitHub Desktop.
Fluent Type Switch
namespace Utilities
{
using System;
using System.Collections.Generic;
using System.Linq;
public class Switch
{
private readonly ICollection<Func<object, Action>> _cases;
private bool _defaultUsed;
public Switch(params Func<object, Action>[] cases)
{
if (cases == null)
{
_cases = Enumerable.Empty<Func<object, Action>>().ToList();
return;
}
_cases = cases.ToList();
}
public Switch Case<T>(Action<T> action)
{
_cases.Add(o => o is T ? (Action)(() => action((T)o)) : (Action)null);
return this;
}
public Switch Default(Action action)
{
if(_defaultUsed)
throw new InvalidOperationException("Default can only be used once");
_defaultUsed = true;
Case<object>(x => action());
return this;
}
public void Execute(object obj)
{
var @case = _cases
.Select(f => f(obj))
.FirstOrDefault(a => a != null);
if (@case != null)
{
@case();
}
}
}
}
===========================================================================
Usage: // where the various Execute methods are part of the class
1) var @switch = new Switch()
.Case<Test1>(x => x.Execute("hello"))
.Case<Test2>(x => x.Execute("there"))
.Case<Test3>(x => x.Execute("want"))
.Case<Test4>(x => x.Execute("to"))
.Default(() => Console.WriteLine("party"));
var t2 = new Test2();
@switch.Execute(t2); // should execute the second case
2) var @switch = new Switch()
.Case<Test1>(x => x.Execute("hello"))
.Case<Test2>(x => x.Execute("there"))
.Case<Test3>(x => x.Execute("want"))
.Case<Test4>(x => x.Execute("to"))
.Default(() => Console.WriteLine("party"));
var t2 = string.Empty;
@switch.Execute(t2); //Default should be executed
3) var @switch = new Switch()
.Case<Test1>(x => x.Execute("hello"))
.Case<Test2>(x => x.Execute("there"))
.Case<Test3>(x => x.Execute("want"))
.Case<Test4>(x => x.Execute("to"));
var t2 = string.Empty;
@switch.Execute(t2); //should fall through without executing anything
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment