附加处理程序,它将值返回给事件c#

时间:2017-01-26 15:31:58

标签: c# events delegates

我有以下内容:

    public String AttachService(string whereClauseParam)
    {
        //Get Client object here
        Client c = new Client();
        string cookieFromRequest =   WebOperationContext.Current.IncomingRequest.Headers[HttpRequestHeader.Cookie];
        tokenInfo.TryGetValue(cookieFromRequest, out c);
        string[] arr = new string[] { };
        c.AttachedServiceStatus += OnAttachedServiceStatus;
        string whereClause = whereClauseParam.ToString();
        //c.AttachService("binding.interface='query_em'", 8799989);

        return string.Format("attached");
    }

//下面的处理程序代码:

    public string OnAttachedServiceStatus(Client sender, ClientServiceAttachedStatus status)
    {
        if (status.AttachStatus == AttachedStatus.Connected && status.ServiceAttachStatus == ServiceAttachStatus.Attached)
        { 
            //update the Client object in Dictionary
            Client c = new Client();

            var ou = tokenInfo.First(x => x.Value == sender);
            tokenInfo.TryGetValue(ou.Key.ToString(), out c);
            tokenInfo.TryRemove(ou.Key.ToString(), out c);
            tokenInfo.TryAdd(ou.Key.ToString(), sender);

            string[] statusInfoT = new string[200];
            statusInfoT[0] = status.ServiceId.ToString();
            statusInfoT[1] = status.AttachStatus.ToString();
            statusInfoT[2] = status.ServiceAttachStatus.ToString();
            statusInfoT[3] = status.VirtualServiceId.ToString();
            statusInfoT[4] = status.AttachToken.ToString();
            statusInfo.TryAdd(ou.Key.ToString(), statusInfoT);

            //update the UI with a Dispatch - TO BE DONE

        }

        return "Connected";
    }

上面的AttachService方法有一个处理程序" OnAttachedServiceStatus"附加到事件" AttachedServiceStatus"。 只要OnAttachedServiceStatus返回void,它就可以正常工作。但是,我现在需要让Handler OnAttachedServiceStatus返回一个字符串,但我无法正确附加处理程序。

我正在考虑使用Func委托,但不确定如何使用它。 请帮助!

2 个答案:

答案 0 :(得分:1)

首先,事件处理程序的签名由事件的委托类型定义。如果该委托返回void,则您无法附加任何其他方法。方法和返回值的参数都应该匹配偶数委托的签名。我相信AttachedServiceStatus使用返回void的委托。这样的事情:

public delegate void Action<T1, T2>(T1 arg1, T2 arg2)

事件是

public event Action<Client, ClientServiceAttachedStatus> AttachedServiceStatus

但是,如果你将使用返回值的委托怎么办? E.g。

public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2)

您可以将事件声明为

public event Func<Client, ClientServiceAttachedStatus> AttachedServiceStatus

但这没有任何意义。因为事件是代表。当您附加处理程序时,您实际上是在组合委托,创建类似委托列表(调用列表)之类的东西。此列表包含所有附加的处理程序。当您引发事件时,将逐个调用调用列表中的所有处理程序,并且仅返回上次调用的处理程序的结果。调查顺序未确定。所以你甚至不知道哪个处理程序返回了值。

(*)虽然如果你手动调用每个处理程序而不是引发事件,仍然可以获得所有结果。请参阅下面的Servy评论

更新

  

我希望处理程序“OnAttachedServiceStatus”返回一个字符串   到来电者“AttachService”,但我无法得到以下正确的

将事件附加到事件时,不执行处理程序。它刚刚添加到事件的调用列表中。当Client 引发事件时,将执行事件处理程序。所以AttachService不是来电者。 Client是来电者。而且你不能将字符串返回AttachService。将处理程序附加到事件后,代码将退出AttachService方法。一段时间之后将引发事件,并且将执行处理程序,但它与AttachService方法无关。

答案 1 :(得分:0)

我不确定你是否了解事件是如何运作的。

    Client c = new Client();
    // ...
    c.AttachedServiceStatus += OnAttachedServiceStatus;

此处未调用OnAttachedServiceStatus。相反,这告诉Client对象在引发AttachedServiceStatus事件时调用OnAttachedServiceStatus方法,这可能发生在将来的任何时候。这就像你告诉赛车手一样#34;当我说'去'时,尽可能快地跑到终点线然后告诉我你到达那里需要多少步骤&#34 ;。赛车手并没有立即开始跑步,他们也没有告诉你它采取了多少步骤;他们处于准备状态并等待。当你说&#34;去&#34;,当他们执行你的指示并开始跑步时。当你得到他们的回复时,在你给他等待的指示之后,这很好。

从外观上看,您正在尝试建立远程连接,并且希望从服务器确认确实已建立连接。如果使用事件来传达该信息,您将要使用EventArgs来传递它。您应该能够通过以下方式实现这一目标:

客户方:

public String ConnectToServer(string whereClauseParam)
{
    //Create Server object here
    Server s = new Server();
    s.AttachedServiceStatus += OnAttachedServiceStatus;
    s.AttachService(this, whereClauseParam, 8799989);
}


public void OnAttachedServiceStatus (object sender, ClientServiceAttachedEventArgs e)
{
    if (e.AttachStatus == AttachedStatus.Connected && e.ServiceAttachStatus == ServiceAttachStatus.Attached)
    { 
        // Update the UI with the message from the server.
        MessageBox.Show(e.Message);

        // If you need to do something else with the server in response, you can do this:
        ((Server)sender).Foo("bar");
    }
}

在服务器端,为您的活动定义自定义EventArgs类:

// By making this inherit from EventArgs, we can use the built-in EventHandler<T> delegate for the event itself.
public class ClientServiceAttachedEventArgs : EventArgs
{
    public AttachedStatus AttachStatus { get; set; }
    public ServiceAttachStatus ServiceAttachStatus  { get; set; }
    public string Message { get; set; }
    // You can put in as many properties as you want to carry the information back from the server.
}

并将其放入您的Server类:

public event EventHandler<ClientServiceAttachedEventArgs> AttachedServiceStatus;

public String AttachService(Client client, string whereClauseParam, int code)
{
    // Do what you need to do to register the client.
    //...

    // Assuming everything went as planned, fire the event.
    // First, construct the EventArgs with information about the results of the connection.
    ClientServiceAttachedEventArgs e = new ClientServiceAttachedEventArgs();
    e.AttachStatus = AttachedStatus.Connected;
    e.ServiceAttachStatus = ServiceAttachStatus.Attached;
    e.Message = "Attached";

    // This is where your OnAttachedServiceStatus method in the client finally gets called. If the event handler were returning a string, this is where it would be returned to and I can't imagine this does you any good. 
    AttachedServiceStatus(this, e); 
}

这是一个相当基本的实现,您的情况可能更复杂,但它应该指向正确的方向。需要注意的重要一点是,您希望返回给客户端的字符串将作为ClientServiceAttachedEventArgs的一部分与您的状态枚举一起通过该事件。这是通过事件发送信息的首选方式。