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);
}
}
}