Как уведомить объект, из которого был вызван метод - PullRequest
1 голос
/ 04 октября 2010

Я пытаюсь создать простой класс для моих вызовов REST, чтобы в моем приложении не было одного и того же кода в нескольких местах.

Проблема в том, что я не знаю, как уведомить объект, вызвавший метод UploadStringAsync (), изнутри обработчика события UploadStringCompleted ().

Вот мой класс, я добавил комментарии, чтобы отметить место, где я хочу уведомить объект, из которого был вызван метод 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:

Мой модифицированный код после предложений Джейкоба:

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 ]

2 голосов
/ 04 октября 2010

Вы можете изменить свой класс 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 голосов
/ 04 октября 2010

Передайте объект, который нуждается в уведомлении, в метод Post ().Затем передайте этот объект в качестве параметра (используя одну из других перегрузок) в метод UploadStringAsync ().Затем ваш client_UploadStringCompleted может использовать информацию об аргументах события для получения объекта, требующего уведомления.

1 голос
/ 04 октября 2010

Следуя совету Джона, почему бы не определить свой собственный интерфейс, такой как 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!
    }
}     
0 голосов
/ 04 октября 2010

Если это приложение для Windows, вы можете написать собственное событие, а затем вызвать его, чтобы вызывающий код мог обработать это событие.Не уверен, что это применимо к Silvelight.

0 голосов
/ 04 октября 2010

client_UploadStringCompleted - это метод экземпляра. Вы можете просто использовать this.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...