Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <ul> <li>Q&amp;A Style - </li> </ul> <p>Because there was so little available on the topic, and because it was all so diverse, I opted to put something up with a little style - something that I believe is a rather thorough 'event response handler'.</p> <p>In the following code sample ( which I have just updated with my latest rendition ( more to come, more than likely)) you'll find code that supports firing of an event, and eventual returning of data from any methods subsequently executed. The 'Event' class that is used to pass down data to event delegates, will eventually contain a set of EventResults that can be evaluated at a later time. This grants a developer the ability to respond to failed delegates after firing an event.</p> <p>The first class is an 'Event', and contains a few variables that can offer some valuable feedback to your delegates - things like what object the event is coming from, a simple string message, the associated stack, etc.</p> <p>The event class Also contains a collection of 'EventResponses'; which brings us to our second class... An EventResponse. This class has two 'types'; which can offer immediate feedback for sub-execution.</p> <p>How this is achieved is through requirement of the 'SourceEvent' in the EventResponse constructors; And through execution of the 'EventResponse.FinalizeResponse' method - which adds the event response to the associated event. I have just finished modifying the EventResponse to be Disposable, and inside of the Disposal, I examine the EventResponse's SourceEvent, and if the SourceEvent does not contain an entry for the EventResponse I am disposing - I create a new copy of the EventResponse, and run FinalizeResponse on the new copy.</p> <p>The ultimate value of all of this is wide-spread - if you'll note an event In the Event class, called 'OnResponseFailure', and similarly the 'AddResponse' method on the event, you'll note that when an event encounters a response that is considered a 'failure'; it throws an event itself to potentially notify the initial calling method.</p> <p>The Event class also contains a couple of fields that could be used to analyze failure or success inside of responses After execution of all of the delegates; which I'll leave for you to meander through. </p> <p>Similarly, the EventResponse class contains a few fields that can be used to return even more data back up to the method that initiated the event, should it be necessary - things like the Response's Source Object, and a message.</p> <p>I hope this is a helpful Q&amp;A - as I feel that it is going to help ME Greatly in creating robust, responsive code. Happy hunting.</p> <pre><code>using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; namespace MyNamespace.Events { public class EventDriver : IDisposable { #region Supporting Events public List&lt;EventResponse&gt; FireEvent(String EventName, Event Event) { List&lt;EventResponse&gt; ResponseList = new List&lt;EventResponse&gt;(); Type LocalType = this.GetType(); Type TargetType = null; if ((TargetType = this.FindEventType(LocalType, EventName)) == null) { return ResponseList; } else { FieldInfo TargetField = TargetType.GetField(EventName, BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); MulticastDelegate EventDelegates = (MulticastDelegate) TargetField.GetValue(this); if (EventDelegates == null) { return ResponseList; } else { foreach (Delegate TargetDelegate in EventDelegates.GetInvocationList()) { try { Object DelegateResponse = TargetDelegate.DynamicInvoke(new Object[] { Event }); EventResponse Response = (EventResponse)DelegateResponse; ResponseList.Add(Response); } catch (Exception e) { } } return ResponseList; } } } private Type FindEventType(Type RootType, String EventName) { if (RootType == null) { return null; } else if (String.IsNullOrEmpty(EventName)) { return null; } else { FieldInfo EventField = null; foreach (FieldInfo Method in RootType.GetFields(BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)) if (Method.Name == EventName) { EventField = Method; break; } if (EventField == null) { if (RootType.BaseType == null) return null; else return this.FindEventType(RootType.BaseType, EventName); } else { return RootType; } } } #endregion #region Dispoability public virtual void Dispose() { this.FireEvent("OnDispose", new Event(this, "Object is being disposed.")); } #endregion } } using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; using System.Reflection; namespace MyNamespace.Events { #region Delegates public delegate EventResponse EventHandler(Event Event); #endregion #region Enumerations public enum EventResponseType { Success, Failure } #endregion public class Event { #region Events public event EventHandler OnResponseFailure = null; #endregion #region Fields public Object EventSource = null; public DateTime EventTime = DateTime.Now; public String EventMessage = String.Empty; protected StackTrace _EventStackTrace = null; public StackTrace EventStackTrace { get { return this._EventStackTrace; } } protected List&lt;EventResponse&gt; _EventResponses = null; public List&lt;EventResponse&gt; EventResponses { get { List&lt;EventResponse&gt; EventResponses = new List&lt;EventResponse&gt;(); lock (this._EventResponses) { foreach (EventResponse Response in this._EventResponses) EventResponses.Add(Response); } return EventResponses; } } public Boolean HasFailedResponses { get { if (this.FailedResponses.Count &gt; 0) return true; return false; } } public Boolean HasSuccessfulResponses { get { if (this.SucceessfulResponses.Count &gt; 0) return true; return false; } } public List&lt;EventResponse&gt; FailedResponses { get { List&lt;EventResponse&gt; FailedResponses = new List&lt;EventResponse&gt;(); foreach (EventResponse Response in this.EventResponses) if (Response.ResponseType == EventResponseType.Failure) FailedResponses.Add(Response); return FailedResponses; } } public List&lt;EventResponse&gt; SucceessfulResponses { get { List&lt;EventResponse&gt; SucceededResponses = new List&lt;EventResponse&gt;(); foreach (EventResponse Response in this.EventResponses) if (Response.ResponseType == EventResponseType.Success) SucceededResponses.Add(Response); return SucceededResponses; } } protected List&lt;Event&gt; _ForwardedEvents = null; public List&lt;Event&gt; ForwardedEvents { get { List&lt;Event&gt; FowardedEvents = new List&lt;Event&gt;(); lock (this._ForwardedEvents) foreach (Event ForwardedEvent in this.ForwardedEvents) ForwardedEvents.Add(ForwardedEvent); return ForwardedEvents; } } #endregion #region Constructors protected Event() { this._EventResponses = new List&lt;EventResponse&gt;(); this._EventStackTrace = new StackTrace(); this._ForwardedEvents = new List&lt;Event&gt;(); } public Event(Object EventSource, String EventMessage, DateTime EventTime) : this() { this.EventSource = EventSource; this.EventTime = EventTime; this.EventMessage = EventMessage; return; } public Event(Object EventSource, String EventMessage) : this(EventSource, EventMessage, DateTime.Now) { } #endregion #region Supporting Methods public void AddResponse(EventResponse Response) { lock (this._EventResponses) { this._EventResponses.Add(Response); } if (Response.ResponseType == EventResponseType.Failure) this.TriggerResponseFailure(Response); return; } public EventResponse CreateResponse() { return new EventResponse(this); } public EventResponse CreateResponse(Object ResponseSource, Object ResponseObject, DateTime ResponseTime, String ResponseMessage, EventResponseType ResponseType) { return new EventResponse(this, ResponseSource, ResponseObject, ResponseTime, ResponseMessage, ResponseType); } public EventResponse CreateResponse(Object ResponseSource, Object ResponseObject, DateTime ResponseTime, EventResponseType ResponseType) { return this.CreateResponse(ResponseSource, ResponseObject, ResponseTime, String.Empty, ResponseType); } public EventResponse CreateResponse(Object ResponseSource, Object ResponseObject, DateTime ResponseTime) { return this.CreateResponse(ResponseSource, ResponseObject, ResponseTime, EventResponseType.Success); } public EventResponse CreateResponse(Object ResponseSource, Object ResponseObject, EventResponseType ResponseType) { return this.CreateResponse(ResponseSource, ResponseObject, DateTime.Now, ResponseType); } public EventResponse CreateResponse(Object ResponseSource, Object ResponseObject) { return this.CreateResponse(ResponseSource, ResponseObject, EventResponseType.Success); } public EventResponse CreateResponse(Object ResponseSource, String ResponseMessage) { return this.CreateResponse(ResponseSource, null, DateTime.Now, ResponseMessage, EventResponseType.Success); } public EventResponse CreateResponse(String ResponseMessage) { return this.CreateResponse(null, ResponseMessage); } public EventResponse CreateResponse(Object ResponseSource) { return this.CreateResponse(ResponseSource, String.Empty); } public Event Forward(Object ForwardFrom) { Event ForwardedEvent = new Event(ForwardFrom, this.EventMessage, this.EventTime); lock (this._ForwardedEvents) this._ForwardedEvents.Add(ForwardedEvent); return ForwardedEvent; } #endregion #region Event Triggers protected void TriggerResponseFailure(EventResponse Response) { if (this.OnResponseFailure != null) this.OnResponseFailure(new Event(Response, "A failure was encountered while executing this event.")); return; } #endregion } public class EventResponse : IDisposable { #region Fields protected Event _SourceEvent = null; public Event SourceEvent { get { return this._SourceEvent; } } public Object ResponseSource = null; public Type ResponseSourceType { get { return this.ResponseSource.GetType(); } } public Object ResponseObject = null; public Type ResponseObjectType { get { return this.ResponseObject.GetType(); } } public DateTime ResponseTime = DateTime.Now; public String ResponseMessage = String.Empty; protected StackTrace _ResponseStackTrace = null; public StackTrace ResponseStackTrace { get { return this._ResponseStackTrace; } } public EventResponseType ResponseType = EventResponseType.Success; #endregion #region Constructors public EventResponse(Event SourceEvent) { this._SourceEvent = SourceEvent; this._ResponseStackTrace = new StackTrace(); } public EventResponse(Event SourceEvent, Object ResponseSource, Object ResponseObject, DateTime ResponseTime, String ResponseMessage, EventResponseType ResponseType) : this(SourceEvent) { this.ResponseSource = ResponseSource; this.ResponseObject = ResponseObject; this.ResponseTime = ResponseTime; this.ResponseMessage = ResponseMessage; this.ResponseType = ResponseType; return; } public EventResponse(Event SourceEvent, Object ResponseSource, Object ResponseObject, DateTime ResponseTime, EventResponseType ResponseType) : this(SourceEvent,ResponseSource,ResponseObject,ResponseTime,String.Empty,ResponseType) { } public EventResponse(Event SourceEvent, Object ResponseSource, Object ResponseObject, DateTime ResponseTime) : this(SourceEvent, ResponseSource, ResponseObject, ResponseTime, EventResponseType.Success) { } public EventResponse(Event SourceEvent, Object ResponseSource, Object ResponseObject, EventResponseType ResponseType) : this(SourceEvent, ResponseSource, ResponseObject, DateTime.Now, ResponseType) { } public EventResponse(Event SourceEvent, Object ResponseSource, Object ResponseObject) : this(SourceEvent, ResponseSource, ResponseObject, EventResponseType.Success) { } public EventResponse(Event SourceEvent, Object ResponseSource, EventResponseType ResponseType) : this(SourceEvent, ResponseSource, null, DateTime.Now, String.Empty, ResponseType) { } public EventResponse(Event SourceEvent, Object ResponseSource, String ResponseMessage) : this(SourceEvent, ResponseSource, null, DateTime.Now, ResponseMessage, EventResponseType.Success) { } public EventResponse(Event SourceEvent, String ResponseMessage) : this( SourceEvent, null, ResponseMessage ) { } #endregion #region Supporting Methods public void FinalizeResponse() { this.SourceEvent.AddResponse(this); return; } #endregion #region Overrides public void Dispose() { if (this.SourceEvent == null) return; else if (this.SourceEvent.EventResponses.Contains(this)) return; else { EventResponse NewResponse = new EventResponse(this.SourceEvent, this.ResponseSource, this.ResponseObject, this.ResponseTime, this.ResponseMessage, this.ResponseType); NewResponse.FinalizeResponse(); return; } } #endregion } } </code></pre> <p>More than likely I'll make more changes to all of this, add more constructors, and method overrides - but this is the version of the code I am currently using and it is performing marvelously for me.</p> <p>The suggestion here is to extend your 'base' class with the 'EventDriver' class - this will give you the ability to use the 'EventDriver.FireEvent' method - which will return all EventResponses generated by a particular event.</p> <p>All of this is fairly 'beta' and like I said I'll still be making changes, but this will be updated accordingly as I make further steps. Enjoy :)</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload