[英]How can I handle return values from event delegates in C#?
因此,我感到很好奇,因為我開發的越多,就越有從事件中獲取數據的用途,因此,我四處張望,並指出,處理事件響應的信息方式不多代表。
擁有一個具有返回值的委托,執行所述委托的方法,並獲取其返回值是一回事,但是當事件觸發眾多委托時,您會怎么做? 您如何確定每個代表的情況?
public delegate object GetObject();
public event GetObject MyEvent;
public IList<object> RaiseMyEvent()
{
var myList = new List<object>();
if (MyEvent != null)
foreach (var handler in MyEvent.GetInvocationList())
myList.Add(handler.DynamicInvoke());
return myList;
}
因為該主題上的可用信息很少,並且因為它是如此多樣化,所以我選擇提出一些帶有一點風格的東西-我認為這是一個相當徹底的“事件響應處理程序”。
在下面的代碼示例中(我剛剛用最新的演示文稿進行了更新(更多內容,很有可能)),您將找到支持事件觸發以及最終從隨后執行的任何方法返回數據的代碼。 用於將數據傳遞給事件委托的'Event'類最終將包含一組EventResults,可以在以后進行評估。 這使開發人員能夠在觸發事件后響應失敗的委托。
第一類是“事件”,其中包含一些變量,可以為您的委托人提供一些有價值的反饋-諸如事件來自哪個對象,簡單的字符串消息,關聯的堆棧等。
事件類還包含“ EventResponses”的集合; 這使我們進入了第二堂課……EventResponse。 此類有兩種“類型”。 可以立即為子執行提供反饋。
這是通過EventResponse構造函數中對'SourceEvent'的要求實現的; 並通過執行'EventResponse.FinalizeResponse'方法-將事件響應添加到關聯的事件。 我剛剛將EventResponse修改為Disposable,然后在Disposal中,檢查了EventResponse的SourceEvent,如果SourceEvent不包含我要處置的EventResponse的條目,請創建新的EventResponse副本,然后運行對新副本的FinalizeResponse。
所有這些功能的最終價值是廣泛的-如果您注意到一個事件在Event類中稱為“ OnResponseFailure”,並且類似地在該事件上使用“ AddResponse”方法,則您會注意到,當事件遇到被認為是“失敗”的響應; 它本身會引發一個事件,以潛在地通知初始調用方法。
Event類還包含幾個字段,可用於分析響應中的失敗或成功。 我會留給你走一走。
同樣,EventResponse類包含一些字段,可用於在需要時將更多數據返回到發起事件的方法中,例如響應的源對象和消息。
我希望這是一個有用的問答-因為我認為這將極大地幫助我創建健壯的響應式代碼。 狩獵愉快。
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<EventResponse> FireEvent(String EventName, Event Event)
{
List<EventResponse> ResponseList = new List<EventResponse>();
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<EventResponse> _EventResponses = null;
public List<EventResponse> EventResponses
{
get
{
List<EventResponse> EventResponses = new List<EventResponse>();
lock (this._EventResponses)
{
foreach (EventResponse Response in this._EventResponses)
EventResponses.Add(Response);
}
return EventResponses;
}
}
public Boolean HasFailedResponses
{
get
{
if (this.FailedResponses.Count > 0)
return true;
return false;
}
}
public Boolean HasSuccessfulResponses
{
get
{
if (this.SucceessfulResponses.Count > 0)
return true;
return false;
}
}
public List<EventResponse> FailedResponses
{
get
{
List<EventResponse> FailedResponses = new List<EventResponse>();
foreach (EventResponse Response in this.EventResponses)
if (Response.ResponseType == EventResponseType.Failure)
FailedResponses.Add(Response);
return FailedResponses;
}
}
public List<EventResponse> SucceessfulResponses
{
get
{
List<EventResponse> SucceededResponses = new List<EventResponse>();
foreach (EventResponse Response in this.EventResponses)
if (Response.ResponseType == EventResponseType.Success)
SucceededResponses.Add(Response);
return SucceededResponses;
}
}
protected List<Event> _ForwardedEvents = null;
public List<Event> ForwardedEvents
{
get
{
List<Event> FowardedEvents = new List<Event>();
lock (this._ForwardedEvents)
foreach (Event ForwardedEvent in this.ForwardedEvents)
ForwardedEvents.Add(ForwardedEvent);
return ForwardedEvents;
}
}
#endregion
#region Constructors
protected Event()
{
this._EventResponses = new List<EventResponse>();
this._EventStackTrace = new StackTrace();
this._ForwardedEvents = new List<Event>();
}
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
}
}
我很有可能會對所有這些進行更多更改,添加更多的構造函數,並重寫方法-但這是我當前正在使用的代碼的版本,它對我來說是出色的。
這里的建議是用'EventDriver'類擴展'base'類-這將使您能夠使用'EventDriver.FireEvent'方法-將返回由特定事件生成的所有EventResponses。
所有這些都是相當“ beta”的,就像我說的那樣,我仍然會進行更改,但是隨着我進行進一步的操作,此更改將相應地進行更新。 請享用 :)
通常,將引發一個事件的代碼,該事件的訂戶應返回其訂戶應返回信息,該代碼將向其訂戶傳遞一個事件對象,該事件對象具有訂戶可以在其中放置信息的字段或訂戶可以向其提供信息的對象。 在只有第一個有話要說的用戶感興趣的情況下,首選使用前一種用法。 在許多訂戶都可能要添加一些內容的情況下,最好使用后一種用法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.