using System; using System.CodeDom; using System.Linq; using System.Reflection; using Chernobyl.Event; namespace Chernobyl.Reflection.Template.CodeDom { /// /// An that can take any /// instance that represents an event and generate CodeDom for it. /// public class CodeDomEvent : CodeDomMember { /// /// Initializes a new instance of the class. /// /// The instance to /// generate CodeDom for and provide the /// implementation for this class. /// Thrown if the member is not /// a event. In other words, the /// on the is not equal to /// . public CodeDomEvent(IMember member) : base(member) { if (Info.MemberType != MemberTypes.Event) throw new ArgumentException("The member must be an event.", "member"); AttachStatement.Event.EventName = EventName; } /// /// 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(); } } } /// /// The qualifier that exists in front of the name of an event members /// 'add' method. For example, if an event was named "SomeEvent", then /// the add method for that event would be "add_SomeEvent". /// public const string AddNameQualifier = "add_"; /// /// The qualifier that exists in front of the name of an event members /// 'remove' method. For example, if an event was named "SomeEvent", /// then the remove method for that event would be "remove_SomeEvent". /// public const string RemoveNameQualifier = "remove_"; /// /// 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 (AttachStatement.Listener != null || e.Items.Length > 1) throw new Exception("Unable to add new argument expression. This member only supports one argument."); AttachStatement.Listener = e.Items.First(); InitializeMethod.Statements.Add(AttachStatement); 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(AttachStatement); AttachStatement.Listener = null; base.ArgumentExpressionRemoved(sender, e); } /// /// The CodeDom method where the value of the member is set (in the case /// of a field, property, etc) or the method is invoked. By default, this /// is set to the . Note /// that, when set, this property will move the /// from the old /// to the newly specified one. /// public override CodeMemberMethod InitializeMethod { get { return base.InitializeMethod; } set { CodeMemberMethod previousInitializeMethod = InitializeMethod; base.InitializeMethod = value; // If a new InitializeMethod has been set that is not null and // we've already added our AttachStatement to the old // InitializeMethod then we need to move the AttachStatement to // the new InitializeMethod. if(base.InitializeMethod == value && value != null && previousInitializeMethod.Statements.Contains(AttachStatement) == true) { previousInitializeMethod.Statements.Remove(AttachStatement); base.InitializeMethod.Statements.Add(AttachStatement); } } } /// /// Initializes a portion of this . This /// method is called after the parent is set so that the necessary /// CodeDom instances can be retrieved from the parent /// . /// void Configure() { // note that we don't configure the AttachStatement.Event.TargetObject // if our Parent is not set to a CodeDomInstance because the property // TheGenericInstancePropertyReference uses the CodeDomInstance // Parent reference to generate the required code. if (Parent != null && Parent is CodeDomInstance && AttachStatement.Event.TargetObject == null) AttachStatement.Event.TargetObject = TheGenericInstancePropertyReference; } /// /// The name of the event without the "add_" or "remove_" event /// qualifiers. /// string EventName { get { if (_eventName == null) { if (Name.StartsWith(AddNameQualifier) == true) _eventName = Name.Remove(0, AddNameQualifier.Length); else if (Name.StartsWith(RemoveNameQualifier) == true) _eventName = Name.Remove(0, RemoveNameQualifier.Length); else _eventName = Name; } return _eventName; } } /// /// The statement that generates the event attachment code. /// public CodeAttachEventStatement AttachStatement { get { if(_attachStatement == null) { _attachStatement = new CodeAttachEventStatement { Event = new CodeEventReferenceExpression() }; } return _attachStatement; } } /// /// The backing field to . /// string _eventName; /// /// The backing field to . /// CodeAttachEventStatement _attachStatement; } }