using System;
using System.CodeDom;
using System.Reflection;
using Chernobyl.Event;
namespace Chernobyl.Reflection.Template.CodeDom
{
///
/// An that can take any
/// instance that represents an array constructor and generate CodeDom for
/// it.
///
public class CodeDomArrayConstructor : CodeDomMember
{
///
/// Initializes a new instance of the
/// class.
///
/// The instance to
/// generate CodeDom for and provide the
/// implementation for this class.
public CodeDomArrayConstructor(IMember member)
: base(member)
{
if (Info.MemberType != MemberTypes.Constructor)
throw new ArgumentException("The member must be a constructor.", "member");
}
///
/// 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)
{
bool statementCreated = CreateExpression != null;
// create the expression and statement if it already hasn't been created
if (statementCreated == false)
{
CreateExpression = new CodeArrayCreateExpression(Instance.Type);
ConfigureAssignmentStatement();
}
CreateExpression.Initializers.AddRange(e.Items);
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)
{
foreach (CodeExpression codeExpression in e.Items)
CreateExpression.Initializers.Remove(codeExpression);
if (CreateExpression.Initializers.Count == 0)
{
if (AssignmentStatement != null)
{
InitializeMethod.Statements.Remove(AssignmentStatement);
AssignmentStatement = null;
}
CreateExpression = null;
}
base.ArgumentExpressionRemoved(sender, e);
}
///
/// 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)
{
// CodeDomInstance automatically add a creation statement
// to their constructors. We are now this instance's
// constructor so have the default constructor removed.
CodeDomInstance codeDomParent = base.Parent as CodeDomInstance;
if (codeDomParent != null && codeDomParent.CreationStatement != null)
codeDomParent.ClassConstructor.Statements.Remove(codeDomParent.CreationStatement);
ConfigureAssignmentStatement();
}
}
}
}
///
/// Creates and sets up the . This
/// method requires that the parent has been set before it is invoked
/// and that the parent is of type .
///
void ConfigureAssignmentStatement()
{
// Note that we don't configure the AssignmentStatement if our
// Parent is not set to a CodeDomInstance because the property
// TheGenericInstancePropertyReference uses the CodeDomInstance
// Parent reference to generate the required code.
if (CreateExpression != null && AssignmentStatement == null &&
Parent != null && Parent is CodeDomInstance)
{
AssignmentStatement = new CodeAssignStatement(TheGenericInstancePropertyReference, CreateExpression);
InitializeMethod.Statements.Add(AssignmentStatement);
}
}
///
/// The that represents the creation of the
/// array using the constructor.
///
CodeArrayCreateExpression CreateExpression { get; set; }
///
/// The that represents the assignment of the
/// instance in CodeDom.
///
CodeAssignStatement AssignmentStatement { get; set; }
}
}