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

时间:2010-10-04 16:42:58

标签: c# silverlight silverlight-4.0

我正在尝试为我的REST调用创建一个简单的类,所以我的应用程序中的多个位置都没有相同的代码。

问题是,我不知道如何从UploadStringCompleted()事件处理程序中通知一个调用UploadStringAsync()方法的对象。

这是我的班级,我添加了注释来标记我想要通知调用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);
        }
    }
}

编辑:

雅各布的建议之后修改了我的代码:

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

这就是我调用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.";
        }
    }

5 个答案:

答案 0 :(得分:2)

将需要通知的对象传递给Post()方法。然后,将该对象作为参数(使用其他重载之一)传递给UploadStringAsync()方法。然后,您的client_UploadStringCompleted可以使用事件参数信息来获取需要通知的对象。

答案 1 :(得分:2)

您可以修改Rest类,以便为其提供回调委托而不是要通知的对象。它可能看起来像这样:

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

然后,当您发出请求时,调用将如下所示:

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


// ...

private void handleResult(UploadStringCompletedEventArgs result)
{
}

答案 2 :(得分:1)

根据John的建议,为什么不定义自己的界面,比如IDoSomethingAfterRest。在任何使用您的Rest类的对象上实现它。当Rest调用完成,并且控制在client_UploadStringCompleted函数中时,只需调用要执行的IDoSomethingAfterRest中的方法。

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

在正在调用Post的对象上实现接口:

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

现在,在您的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!
    }
}     

答案 3 :(得分:0)

client_UploadStringCompleted是一种实例方法。您只需使用this

即可

答案 4 :(得分:0)

如果它是一个Windows应用程序,你可以编写自己的事件,然后提高它,以便调用代码可以处理该事件。不确定它是否适用于Silvelight。