using System; namespace Chernobyl.Switch { /// <summary> /// An <see cref="ISwitch"/> that fires an event when it's /// <see cref="Count"/> reaches zero. The <see cref="Count"/> is reduced by /// one every time the <see cref="Countdown(object, EventArgs)"/> event /// handler method is invoked. /// </summary> public class CountdownSwitch : ISwitch { /// <summary> /// Initializes a new instance of the <see cref="CountdownSwitch"/> class. /// </summary> /// <param name="count">The count of this <see cref="CountdownSwitch"/>. /// When this <see cref="Count"/> reaches zero, the /// <see cref="SwitchedOn"/> event will be raised. This /// <see cref="Count"/> is decremented every time /// <see cref="Countdown(object, EventArgs)"/> is invoked. The value of /// this parameter must be greater than 0.</param> /// <exception cref="ArgumentException">Thrown if the countdown /// <paramref name="count"/> is 0; you cannot countdown from zero.</exception> public CountdownSwitch(uint count) { Count = StartingCount = count; } /// <summary> /// An event handler that can be assigned to an event. This method will /// decrement the <see cref="Count"/> by one every time it is invoked. /// When the <see cref="Count"/> reaches zero the /// <see cref="SwitchedOn"/> event will be raised. /// </summary> /// <param name="sender">The instance that generated the event.</param> /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> public void Countdown(object sender, EventArgs e) { // if we are already at zero, ignore the countdown. if(Count != 0) { --Count; if (Count == 0 && SwitchedOn != null) SwitchedOn(this, EventArgs.Empty); } } /// <summary> /// An event that is raised when the <see cref="Count"/> has reached /// zero. /// </summary> public event EventHandler SwitchedOn; /// <summary> /// An event that is raised right after this switch has been reset using /// the <see cref="Reset()"/> or <see cref="Reset(object, EventArgs)"/> /// methods. /// </summary> public event EventHandler SwitchedOff; /// <summary> /// Resets the switch to its original state or the its state after right /// after its creation. This method will invoke the /// <see cref="SwitchedOff"/> event. /// </summary> public void Reset() { Count = StartingCount; if(SwitchedOff != null) SwitchedOff(this, EventArgs.Empty); } /// <summary> /// An event handler that can be assigned to an event. This event handler /// will reset the switch to its original state. It is exactly the same /// as calling <see cref="Reset()"/>. /// </summary> /// <param name="sender">The sender of the event.</param> /// <param name="e">The arguments to the event.</param> public void Reset(object sender, EventArgs e) { Reset(); } /// <summary> /// The current count of this <see cref="CountdownSwitch"/>. When this /// <see cref="Count"/> reaches zero, the <see cref="SwitchedOn"/> event /// will be invoked. This <see cref="Count"/> is decremented every time /// <see cref="Countdown(object, EventArgs)"/> is invoked. /// </summary> public uint Count { get; private set; } /// <summary> /// The starting value of the <see cref="Count"/>. This is the value /// that was received in the constructor. /// </summary> /// <exception cref="ArgumentException">Thrown if the starting count /// <paramref name="value"/> is set to 0; you cannot countdown from zero.</exception> public uint StartingCount { get { return _startingCount; } private set { if (value == 0) throw new ArgumentException("The countdown starting count " + "cannot be zero since you cannot countdown from zero.", "value"); _startingCount = value; } } /// <summary> /// The backing field to <see cref="StartingCount"/>. /// </summary> uint _startingCount; } }