简体   繁体   English

如何通知已从中调用方法的对象

[英]How to notify object from which a method has been called

I'm trying to make a simple class for my REST calls so I won't have the same code in multiple places in my application. 我正在尝试为我的REST调用创建一个简单的类,这样我的应用程序中不会在多个地方使用相同的代码。

The problem is, I don't know how to notify an object that called the UploadStringAsync() method from inside the UploadStringCompleted() event handler. 问题是,我不知道如何从UploadStringCompleted()事件处理程序内部通知名为UploadStringAsync()方法的对象。

Here is my class, I have added comments to mark the place where I want to notify the object from which the Post method has been called: 这是我的课程,我添加了注释以标记要通知调用Post方法的对象的位置:

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace MyProject.Utils
{
    public class Rest
    {
        private WebClient client = new WebClient();

        private void Init()
        {
            client.UploadStringCompleted += new UploadStringCompletedEventHandler(client_UploadStringCompleted);
        }

        public void Post(string uri, string postRequest, object objectToNotify)
        {
            Init();
            client.Headers["Content-Type"] = "application/x-www-form-urlencoded";
            client.UploadStringAsync(new Uri(uri,
                UriKind.RelativeOrAbsolute), "POST", postRequest, objectToNotify);
        }

        private void client_UploadStringCompleted(object sender,
           UploadStringCompletedEventArgs e)
        {
            // here I would like to notify an object from 
            // which the Post() method has been called
            // I don't know how to do this as this method has no idea
            // which object called the method
            // this doesn't work:
            // (e.UserState.GetType())e.UserState.RestCallback(e);
        }
    }
}

EDIT: 编辑:

My modified code after Jacob's suggestions: 我根据Jacob的建议修改了代码:

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Browser;

namespace MyProject.Utils
{
    public class Rest
    {
        private WebClient client = new WebClient();

        private void Init()
        {
            client.UploadStringCompleted += new UploadStringCompletedEventHandler(client_UploadStringCompleted);
        }

        public void Post(
            string uri, string postRequest,
            Action<UploadStringCompletedEventArgs> callback)
        {
            HtmlPage.Window.Alert("bbb");
            client.Headers["Content-Type"] = "application/x-www-form-urlencoded";
            client.UploadStringAsync(new Uri(uri,
                UriKind.RelativeOrAbsolute), "POST", postRequest, callback);
        }

        private void client_UploadStringCompleted(object sender,
           UploadStringCompletedEventArgs result)
        {
            HtmlPage.Window.Alert("aaa");
            var callback = (Action<UploadStringCompletedEventArgs>)result.UserState;
            callback(result);
        }
    }
}

This is how I'm calling the Post method: 这就是我调用Post方法的方式:

    string postRequest = "id=5":
    Rest restClient = new Rest();
    restClient.Post("http://mywebsite.com/", postRequest, RestCallback);

    .......................

    private void RestCallback(UploadStringCompletedEventArgs result)
    {
        if (result.Error != null)
        {
            ContactFormSuccess.Text = "There was an error sending email message.";
        }
        else
        {
            ContactFormSuccess.Text = "Email message successfully sent.";
        }
    }

Pass the object which needs the notification to the Post() method. 将需要通知的对象传递给Post()方法。 Then, pass that object as a parameter (using one of the other overloads) to the UploadStringAsync() method. 然后,将该对象作为参数(使用其他重载之一)传递给UploadStringAsync()方法。 Then, your client_UploadStringCompleted can use the event arguments information to get the object that needs notification. 然后,您的client_UploadStringCompleted可以使用事件参数信息来获取需要通知的对象。

You could modify your Rest class so that it's given a callback delegate rather than the object to notify. 您可以修改Rest类,以便为它提供一个回调委托,而不是要通知的对象。 It could look something like this: 它可能看起来像这样:

public void Post(
    string uri, string postRequest, 
    Action<UploadStringCompletedEventArgs> callback)
{
    Init();
    client.Headers["Content-Type"] = "application/x-www-form-urlencoded";
    client.UploadStringAsync(
        new Uri(uri, UriKind.RelativeOrAbsolute), 
        "POST", postRequest, callback);
}

private void client_UploadStringCompleted(object sender,
   UploadStringCompletedEventArgs e)
{
    var callback = (Action<UploadStringCompletedEventArgs>)e.UserState;
    callback(e);
}

Then, when you make the request, the call would look something like this: 然后,当您发出请求时,调用将类似于以下内容:

var restClient = new Rest();
restClient.Post("http://your/url", "stuff", handleResult);


// ...

private void handleResult(UploadStringCompletedEventArgs result)
{
}

Following John's suggestion, why not define your own interface, like IDoSomethingAfterRest. 按照John的建议,为什么不定义自己的接口,例如IDoSomethingAfterRest。 Implement it on any object that uses your Rest class. 在使用Rest类的任何对象上实现它。 When the Rest call completes, and control is in the client_UploadStringCompleted function, simply call the method in IDoSomethingAfterRest that you want to execute. 当Rest调用完成并且控件在client_UploadStringCompleted函数中时,只需在IDoSomethingAfterRest中调用要执行的方法即可。

public interface IDoSomethingAfterPost
{
  void DoSomethingAfterPost(<some parameters here>);
}

On your object that is calling Post implement the interface: 在调用Post的对象上实现接口:

public DoSomethingAfterPost(<some parameters here>)
{
  Console.WriteLine("Just finished posting something");
}

Now, in your Rest class, when it is notified that the upload is complete, you can call back on the interface: 现在,在您的Rest类中,当通知上传已完成时,您可以在界面上进行回调:

private void client_UploadStringCompleted(object sender,        
       UploadStringCompletedEventArgs e)        
{
    IDoSomethingAfterPost dsap = e.UserState as IDoSomethingAfterPost;
    if (dsap != null)
    {        
      _caller.DoSomethingAfterPost(e);
    }
    else
    {
      //Whoops!  Someone needs to implement IDoSomethingAfterPost!
    }
}     

client_UploadStringCompleted is an instance method. client_UploadStringCompleted是一个实例方法。 You can simply use this . 您可以简单地使用this

If it is a windows application, you can write your own event and then raise it so that the calling code can handle that event. 如果它是Windows应用程序,则可以编写自己的事件,然后引发该事件,以便调用代码可以处理该事件。 Not sure if it is applicable to Silvelight though. 虽然不确定它是否适用于Silvelight。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM