using Chernobyl.Event; using Chernobyl.Values; namespace Chernobyl.DesignPatterns.Extension { /// /// Attaches/detaches an to/from an /// whenever either of them is modified. /// /// The type of that is to /// have the to it. class Attach { /// /// Initializes a new instance of the class. /// /// will be attached /// to the instance contained this . If the /// instance is not yet provided (equal to null) then /// will be attached when it is. When the /// instance is modified, the will be /// removed from the old instance and placed on the new instance. /// The /// contained in this will be attached to /// . If the /// is not yet provided then it will be attached /// when it is. When the is modified, the /// old version will be detached and the new version will be attached. public Attach(IValue extendable, IValue> attachment) { extendable.Provide += OnExtendableProvided; attachment.Provide += OnAttachmentProvided; } /// /// Invoked when the extendable value is provided. This method attaches /// the attachment to the extendable provided. /// /// The sender of the event. /// The arguments containing the extendable value. void OnExtendableProvided(object sender, ValueChangedEventArgs e) { _extendable = e.NewValue; // Attach to the new value. This will also detach from the // old value. if (_attachment != null) _attachment.Extended = _extendable; } /// /// Invoked when the attachment value is provided. This method attaches /// the attachment to the extendable and detaches the old extendable. /// /// The sender of the event. /// The arguments containing the attachment value. void OnAttachmentProvided(object sender, ValueChangedEventArgs> e) { // Detach the old attachment. if (_attachment != null) _attachment.Extended = default(T); _attachment = e.NewValue; // Attach the new attachment. It is OK if the _extendable is null // since it will just ignore the value passed in (provided it is // properly created). if (_attachment != null) _attachment.Extended = _extendable; } /// /// The instance is to be attached to. /// T _extendable; /// /// The instance to be attaached to . /// IExtension _attachment; } /// /// Utility and extension methods for or its use. /// public static class AttachExtensions { /// /// Attaches/detaches an to/from an /// whenever either of them is modified. /// /// /// The type of that is to /// have the to it. /// /// will be attached /// to the instance contained this . If the /// instance is not yet provided (equal to null) then /// will be attached when it is. When the /// instance is modified, the will be /// removed from the old instance and placed on the new instance. /// /// The /// contained in this will be attached to /// . If the /// is not yet provided then it will be attached /// when it is. When the is modified, the /// old version will be detached and the new version will be attached. public static void Attach(this IValue extendable, IValue> attachment) where T : IExtendable { Attach attach = new Attach(extendable, attachment); } } }