using System;
using System.CodeDom;
using System.Linq;
using Chernobyl.Event;
namespace Chernobyl.Reflection.Template.CodeDom
{
///
/// An that can take any
/// instance that represents a property and generate CodeDom for it.
///
public abstract class CodeDomAssignableMember : CodeDomMember
{
///
/// Initializes a new instance of the class.
///
/// The instance to
/// generate CodeDom for and provide the
/// implementation for this class.
protected CodeDomAssignableMember(IMember member)
: base(member)
{ }
///
/// 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.
///
public override IComponent Parent
{
get { return base.Parent; }
set
{
if (base.Parent != value)
{
base.Parent = value;
if (base.Parent == value)
Configure();
}
}
}
///
/// An event handler that is invoked right after an argument
/// s are added to the
/// list.
///
/// The instance that generated the event.
/// The instance
/// containing the event data.
protected override void ArgumentExpressionAdded(object sender, ItemsEventArgs e)
{
if (MemberSetStatement != null || e.Items.Length > 1)
throw new Exception("Unable to add new argument expression. This member only supports one argument.");
_argument = e.Items.First();
Configure();
base.ArgumentExpressionAdded(sender, e);
}
///
/// An event handler that is invoked right after an argument
/// s are removed from the
/// list.
///
/// The instance that generated the event.
/// The instance
/// containing the event data.
protected override void ArgumentExpressionRemoved(object sender, ItemsEventArgs e)
{
InitializeMethod.Statements.Remove(MemberSetStatement);
MemberSetStatement = null;
_argument = null;
base.ArgumentExpressionRemoved(sender, e);
}
///
/// Initializes the . Note to
/// implementers: Base classes should invoke the base class
/// method when their
/// is initialized.
///
protected virtual void Configure()
{
if(MemberSetStatement == null)
{
MemberSetStatement = new CodeAssignStatement();
InitializeMethod.Statements.Add(MemberSetStatement);
}
if (MemberSetStatement.Left == null && AssignableMemberReference != null)
MemberSetStatement.Left = AssignableMemberReference;
if (MemberSetStatement.Right == null && _argument != null)
{
MemberSetStatement.Right = _argument;
// we don't need the argument variable anymore
_argument = null;
}
}
///
/// The reference to the assignable member as a code expression or null
/// if it has not yet been set up. This reference will be used to
/// generate code that can set the member.
///
public abstract CodeExpression AssignableMemberReference { get; }
///
/// The that represents the setting of the
/// member or null if this hasn't been
/// created yet because an argument hasn't been added.
///
CodeAssignStatement MemberSetStatement { get; set; }
///
/// The that represents the argument that
/// is set on this member or null if the argument has not been added,
/// it was removed, or it was finally set onto the
/// 's
/// property.
///
CodeExpression _argument;
}
}