using System;
using System.Collections;
using System.Collections.Generic;
using Chernobyl.Collections.Generic;
using Chernobyl.Collections.Generic.Event;
using Chernobyl.Collections.Generic.Hierarchy;
namespace Chernobyl.Reflection.Template
{
///
/// An that allows for at runtime switching of
/// it's implementation and makes creating new s
/// easier through the use of other implementations.
/// This is an implementation of the decorator pattern
/// (http://en.wikipedia.org/wiki/Decorator_pattern).
///
public abstract class ComponentDecorator : IComponent
{
///
/// Initializes a new instance of the class.
/// Note to implementors: this constructor immediately configures the
/// using the
/// method. This assumes the
/// is ready to use.
///
protected ComponentDecorator()
: this(true)
{ }
///
/// Initializes a new instance of the class.
///
/// True if this instance should be configured
/// immediately, false if the method
/// will be invoked at a later time by the implementing type.
protected ComponentDecorator(bool configure)
{
if (configure == true)
ConfigureImplementer();
}
///
/// The namespace or prefix of this component.
///
public string Prefix
{
get { return DecoratedComponent.Prefix; }
}
///
/// The name of this component which can be used to generate code for
/// this component.
///
public virtual string CodeName
{
get { return DecoratedComponent.CodeName; }
}
///
/// The that is the parent to this
/// . This will be
/// added to the parent 's
/// list. If this
/// is already a child to another then it will
/// be removed from that 's
/// list. Setting null on this property
/// will cause this to be removed from it's
/// parent, if necessary. Note that the
/// does not invoke the 's
/// property because then the
/// would be added to the
/// 's list rather
/// than this instance.
///
public virtual IComponent Parent
{
get { return DecoratedComponent.Parent; }
set { DecoratedComponent.Parent = value; }
}
///
/// Sub-components of this . Note that the
/// does not return the
/// 's
/// property because then the would
/// be set on the added children's property rather
/// than this instance.
///
public IEventCollection ComponentChildren
{
get { return DecoratedComponent.ComponentChildren; }
}
///
/// Gets or sets the name of the instance. This property is made virtual
/// to allow for a name is separate from the
/// .
///
public string Name
{
get { return DecoratedComponent.Name; }
set { DecoratedComponent.Name = value; }
}
///
/// An that iterates over an
/// in depth first order (see
/// http://en.wikipedia.org/wiki/Depth-first_search for more information).
///
///
public IEnumerable DepthFirst
{
get { return DecoratedComponent.DepthFirst; }
}
///
/// An that iterates over an
/// in breadth first order (see
/// http://en.wikipedia.org/wiki/Breadth-first_search for more information).
///
///
public IEnumerable BreadthFirst
{
get { return DecoratedComponent.BreadthFirst; }
}
///
/// Returns an enumerator that iterates through this
/// and the tree
/// underneath it.
///
///
/// A that can
/// be used to iterate through the tree.
///
public IEnumerator GetEnumerator()
{
return DecoratedComponent.GetEnumerator();
}
///
/// Returns an that iterates through this
/// and the tree
/// underneath it.
///
///
/// A that can
/// be used to iterate through the tree.
///
IEnumerator IEnumerable.GetEnumerator()
{
return DecoratedComponent.GetEnumerator();
}
///
/// The that "decorates"
/// (http://en.wikipedia.org/wiki/Decorator_pattern) this
/// . The decorator is used when this
/// needs client code to refer to the
/// decorator rather than this such as when
/// parenting children. In the event that a decorator doesn't exist,
/// this property is set to null.
///
public IComponent Decorator
{
get { return DecoratedComponent.Decorator; }
set { DecoratedComponent.Decorator = value; }
}
///
/// A method that must be invoked by the implementing type so this
/// instance can be properly setup to work with the
/// .
///
protected void ConfigureImplementer()
{
if (_implementerConfigured == false)
{
if (DecoratedComponent == null)
throw new Exception("The DecoratedComponent is null and cannot " +
"be configured. Please pass false to this class' constructor and " +
"invoke ConfigureImplementer() method when the DecoratedComponent " +
"is ready.");
Decorator = this;
_implementerConfigured = true;
}
}
///
/// The instance that implements the
/// functionality of this class.
///
protected abstract IComponent DecoratedComponent { get; }
///
/// True if the method has already
/// been called, false if otherwise.
///
bool _implementerConfigured;
}
}