Функции обратного вызова в C # - PullRequest
2 голосов
/ 17 июля 2011

Я привык к Javascript, где я могу просто передать функцию в качестве параметра для последующего использования в качестве обратного вызова.Это было красиво и легко.

Сейчас я пишу приложение на c # и хочу сделать то же самое.

По сути, мое приложение похоже на следующее и требует токен аутентификации.Однако на этапе getData, если токен истек, мне нужно вызвать refreshToken ().Как передать функцию обратного вызова через refreshToken (), чтобы getData знала, что вызывать при обновлении токена?

Вот схема того, что я буду делать в Javascript, но я бы сделал это в C #или просто передать обратные вызовы в целом?:

getData(callback);
// Looks like the token is expired, exiting the getData function and refreshing token
refreshToken(function(){ getData(callback); });
// Token is refreshed, now call getData()
getData(callback);
// Callback is run

Или, в качестве альтернативы, вместо использования множества обратных вызовов я мог бы выполнять вызов refreshToken синхронно.Однако RestSharp на WP7 по какой-либо причине не показывает Execute, только ExecuteAsync, который я сейчас и использую.Кто-нибудь знает, почему этот метод не существует для меня?

Ответы [ 3 ]

4 голосов
/ 17 июля 2011

Для передачи функции в качестве параметра в C # используется делегат .Делегат указывает ожидаемый тип возвращаемого значения и аргументы функции, передаваемой в метод, и ваш метод обратного вызова должен соответствовать этой спецификации, иначе ваш код не будет компилироваться.

Делегаты обычно объявляются непосредственно в пространстве имен и принимаютформа:

<access modifier(s)> delegate <return type> <DelegateName>([argument list]);

Например, в C # делегат с именем FooCallback, представляющий функцию обратного вызова для метода Foo, который не принимает аргументов и возвращает void, будет выглядеть так:

namespace Demo
{
public delegate void FooCallback();
}

Функция, которая принимает параметр FooCallback, будет выглядеть следующим образом:

namespace Demo
{
//delegate for a FooCallback method from the previous code block
public delegate void FooCallback();

public class Widget
{
public void BeginFoo(FooCallback callback)
{

}

Предполагая, что у вас есть метод, который соответствует сигнатуре делегата, вы можете просто передать его имя в качестве значенияпараметр делегата.Например, если у вас есть функция с именем MyFooCallback, вы можете передать ее в качестве параметра методу StartFoo следующим образом:

using Demo; //Needed to access the FooDelegate and Widget class.

namespace YourApp
{
public class WidgetUser
{
private Widget widget; //initialization skipped for brevity.

private void MyFooCallback()
{
//This is our callback method for StartFoo. Note that it has a void return type
//and no parameters, just like the definition of FooCallback. The signature of
//the method you pass as a delegate parameter MUST match the definition of the
//delegate, otherwise you get a compile-time error.
}
public void UseWidget()
{
//Call StartFoo, passing in `MyFooCallback` as the value of the callback parameter.
widget.BeginFoo(MyFooCallback);
}
}
}

Хотя можно определить делегата с аргументами, этоневозможно передать список аргументов вместе с именем метода, как это обычно делается при вызове метода

namespace Demo
{
 public delegate void FrobCallback(int frobberID);
//Invalid Syntax - Can't pass in parameters to the delegate method this way.
BeginFrob(MyFrobCallback(10))
}

Когда делегат задает параметры, метод, который вызывает делегат, принимает аргументы, необходимые делегату, и передает ихк методу делегата, когда он вызывается:

BeginFrob(MyFrobCallback, 10)

Затем метод BeginFrob вызовет MyFrobCallback с переданным в frobberID значением 10 следующим образом:

public void BeginFrob(FrobCallback callback, int frobberID)
{
//...do stuff before the callback
callback(frobberID);
}

Лямбда-выражения позволяют вам определять метод, в котором он используется, вместо необходимости явно объявлять его

BeginFoo((int frobberID) => {your callback code here;});

Таким образом, делегаты являются средством дляметоды, передаваемые другим методам в качестве параметров.

3 голосов
/ 17 июля 2011

В silverlight / wp7 нет синхронных веб-вызовов, так что это не проблема резкого увеличения.

Как сказал Артур, вам нужны делегаты.

function getData(Action<string> callback) {
  if (token.needRefresh) {
    refrshToken(() => getData(callback) );
    return;
  }
  // get Data
  callback(data);
}

function refreshToken(Action callback) {
  // token.refresh
  callback();
}
2 голосов
/ 17 июля 2011
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...