如何处理C#中事件委托的返回值?

时间:2013-10-18 20:32:28

标签: c# events delegates return-value

所以我自己很好奇,因为我开发的越多,我从事件中获取数据的用途越来越多,所以我做了一个小看,并注意到处理信息的方式并不多来自活动代表的回复。

拥有一个带有返回值的委托是一回事,并执行所述委托的方法,并获得其返回值,但是如果有一个事件触发了大量代表,你会怎么做?你如何确定每个代表中发生的事情?

3 个答案:

答案 0 :(得分:1)

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;
}

答案 1 :(得分:0)

  • Q&amp; A Style -

因为关于这个主题的可用性很少,并且因为它非常多样化,所以我选择用一些小风格来做点什么 - 我认为这是一个相当彻底的'事件响应处理程序'。

在下面的代码示例中(我刚刚使用我的最新版本进行了更新(更多内容,更有可能)),您将找到支持触发事件的代码,并最终从随后执行的任何方法返回数据。用于将数据传递给事件委托的“Event”类最终将包含一组可在以后进行评估的EventResults。这使得开发人员能够在触发事件后响应失败的代理。

第一个类是一个'Event',它包含一些变量,可以为你的代表提供一些有价值的反馈 - 比如事件来自哪个对象,一个简单的字符串消息,相关的堆栈等等。

事件类还包含'EventResponses'的集合;这将我们带到了我们的第二课......一个EventResponse。这个班有两个'类型';这可以为子执行提供即时反馈。

如何通过EventResponse构造函数中的'SourceEvent'的要求来实现这一目标;并通过执行'EventResponse.FinalizeResponse'方法 - 将事件响应添加到关联事件。我刚刚完成将EventResponse修改为Disposable,在Disposal中,我检查了EventResponse的SourceEvent,如果SourceEvent没有包含我正在处理的EventResponse的条目 - 我创建了一个EventResponse的新副本,并运行在新副本上FinalizeResponse。

所有这一切的最终价值是广泛传播的 - 如果您在事件类中注意到事件,称为“OnResponseFailure”,并且类似事件上的“AddResponse”方法,您会注意到事件遇到被视为“失败”的回应;它抛出一个事件本身可能会通知初始调用方法。

Event类还包含几个字段,可用于分析响应中的失败或成功。执行所有委托之后;我将留给你蜿蜒穿过。

类似地,EventResponse类包含一些字段,可用于将更多数据返回到启动事件的方法(如果有必要) - 例如Response的源对象和消息。

我希望这是一个有用的Q&amp; A - 因为我觉得它会帮助我创建强大的响应式代码。快乐的狩猎。

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。

所有这些都是相当“测试版”,就像我说我仍然会进行更改,但随着我采取进一步措施,这将会相应更新。享受:)

答案 2 :(得分:0)

通常,要引发其订户应该返回信息的事件的代码将向其订户传递一个事件对象,该事件对象具有订户可以放置信息的字段,或者订户可以向其提供的对象。前一种用法适用于只有第一个有兴趣的用户会感兴趣的情况。如果许多订阅者都可以添加某些内容,则优先使用后者。