public interface ISubject<T> { void RegisterFor(Expression<Action<T>> action, Action callback); } public interface IObservers { void InformOf(Action action); } public class Observation<T> : IObservers, ISubject<T> { private readonly Dictionary<string, Action> callbacks = new Dictionary<string, Action>(); public void RegisterFor(Expression<Action<T>> action, Action callback) { var key = KeyFrom(action); if (callbacks.ContainsKey(key)) callbacks[key] += callback; else callbacks[key] = callback; } public void InformOf(Action action) { var key = KeyFrom(action); if (callbacks.ContainsKey(key)) callbacks[key](); } private string KeyFrom(Action action) { return action.Method.Name; } private string KeyFrom(Expression<Action<T>> action) { var methodExpressionSignature = (action.Body as MethodCallExpression).ToString(); return ExtractMethodName(methodExpressionSignature); } private string ExtractMethodName(string signature) { return signature.Split(new[] { '.', '(' })[1]; } }
An interface is introduced to specify the actions being observed:
public interface IApplicationState { void Starting(); void Stopping(); } public class Application : IApplicationState { IObservers _observers; public Application(IObservers observers) { _observers = observers; } public void Starting() { /*...*/ _observers.InformOf(Starting); } public void Stopping() { /*...*/ _observers.InformOf(Stopping); } }
An example of use:
static void Main(string[] args) { var observation = new Observation<IApplicationState>(); var app = new Application(observation); observation.RegisterFor(action: change => change.Starting(), callback: () => Console.WriteLine("application is starting.")); app.Starting(); app.Stopping(); Console.ReadLine(); } //OUTPUT: //application is starting.
No comments:
Post a Comment