using System; using Chernobyl.Event; namespace Chernobyl.Values { /// /// An interface which is used to work with types that provided an instance /// that comes from some source. /// /// The type being held within this instance. public interface IValue { /// /// An event that is raised immediately after the value held by this /// instance has been modified or become ready. If an event handler is /// added to this event after the value has become ready, then that /// event handler will be invoked immediately. /// event EventHandler> Provide; } /// /// Utility and extension code for types. /// public static class Value { /// /// Invokes the specified method once when /// is raised. The specified method will not be invoked a second time. /// /// The type being held within this instance. /// The instance whose /// is to be used to invoke . /// The method that is to be invoked once when /// is raised. public static void Request(this IValue value, EventHandler> method) { EventHandler> invokeOnce = null; invokeOnce = (sender, e) => { method(sender, e); value.Provide -= invokeOnce; }; value.Provide += invokeOnce; } /// /// Invokes the specified method whenever the /// is changed and ends the invocation if the method returns false. /// /// The type being held within this instance. /// The instance whose /// is to be used to invoke . /// The method that is to be invoked whenever the /// is changed. This method should return true /// if it wishes to continue to be invoked, false if it wishes invocation /// to end. public static void Notify(this IValue value, Func, bool> method) { EventHandler> invoke = null; bool firstInvoke = true; invoke = (sender, e) => { if (firstInvoke == false) { if (method(sender, e) == false) value.Provide -= invoke; } firstInvoke = false; }; value.Provide += invoke; } /// /// Invokes the specified method whenever the /// is changed. /// /// The type being held within this instance. /// The instance whose /// is to be used to invoke . /// The method that is to be invoked whenever the /// is changed. public static void Notify(this IValue value, EventHandler> method) { value.Notify((o, args) => { method(o, args); return true; }); } /// /// Returns an whose internal value is set to /// null. /// /// The type of the internal value. /// The nulled . public static IValue Null() where T : class { return Default(); } /// /// Returns an whose internal value is set to /// default(T). /// /// The type of the internal value. /// The defaulted . public static IValue Default() { return new BasicContainer(default(T)); } } }