Passer une fonction de rappel à une autre classe


90

J'essaie essentiellement de passer une méthode à une autre classe pour qu'elle soit appelée plus tard, mais je ne peux pas tout à fait comprendre cela en C # (je suis toujours trop habitué à Objective-C).

public class Class1{

    private void btn_click(object sender, EventArgs e)
    {
        ServerRequest sr = new ServerRequest();
        sr.DoRequest("myrequest", myCallback);
    }

    public void myCallback(string str)
    {
    }
}

Ensuite, je veux que ma classe ServerRequest déclenche essentiellement la fonction de rappel, n'est-ce pas possible? (Je téléphone essentiellement à un serveur pour une réponse de connexion à mon logiciel)

Je n'ai pas été en mesure de trouver un moyen de faire cela avec les délégués, je reçois continuellement des erreurs. Voici l'autre classe:

public class ServerRequest
{
    public void DoRequest(string request, Delegate callback)
    {
        // do stuff....
        callback("asdf");
    }
}

Est-ce possible en #? En Objective-C, ce serait simple et je ferais juste quelque chose comme

[myObject performSelector(@selector(MyFunctionName)) withObjects:nil];

Réponses:


139

Vous pouvez le passer comme Action<string>- ce qui signifie que c'est une méthode avec un seul paramètre de type stringqui ne renvoie rien (void):

public void DoRequest(string request, Action<string> callback)
{
    // do stuff....
    callback("asdf");
}

Et comment appelle-t-on DoRequest? Passez-vous une chaîne ou une méthode?
Kokodoko

1
pour les autres curieux d'Action. voici un petit conseil. il peut avoir plusieurs paramètres de type mais pas de retour (pour passer des membres c # uniquement Action <type1, .., typeN> ne permet pas de modificateur sur les types Pour passer la fonction, utilisez à nouveau Func <typeList> pas de modificateur sur tout type le dernier type dans le list est le type de retour de fonction en fait Action et Func sont un moyen rapide d'utiliser des délégués simples
gg89

Faites ma journée, simple et propre!
isanjosgon

24
public class Class1
    {

        private void btn_click(object sender, EventArgs e)
        {
            ServerRequest sr = new ServerRequest();
            sr.Callback += new ServerRequest.CallbackEventHandler(sr_Callback);
            sr.DoRequest("myrequest");
        }

        void sr_Callback(string something)
        {

        }


    }

    public class ServerRequest
    {
        public delegate void CallbackEventHandler(string something);
        public event CallbackEventHandler Callback;   

        public void DoRequest(string request)
        {
            // do stuff....
            if (Callback != null)
                Callback("bla");
        }
    }

10

Vous devez d'abord déclarer le type du délégué car les délégués sont fortement typés:

public void MyCallbackDelegate( string str );

public void DoRequest(string request, MyCallbackDelegate callback)
{
     // do stuff....
     callback("asdf");
}

C'est une excellente solution si vous utilisez la même signature de méthode à de nombreux endroits de votre code.
mtmurdock

4
Il est recommandé de toujours vérifier si la méthode de rappel n'est pas nulle avant de l'appeler.
Maciej

4

Delegateest juste la classe de base donc vous ne pouvez pas l'utiliser comme ça. Vous pourriez faire quelque chose comme ceci:

public void DoRequest(string request, Action<string> callback)
{
     // do stuff....
     callback("asdf");
}

2
Func<string>serait une méthode qui renvoie une chaîne - vous avez besoin d'unAction<string>
BrokenGlass

@BrokenGlass tu as raison mon mauvais - mis à jour (j'ai +1d ta réponse)
Robbie

3

Vous pouvez modifier votre code de cette manière:

public delegate void CallbackHandler(string str);

public class ServerRequest
{
    public void DoRequest(string request, CallbackHandler callback)
    {
        // do stuff....
        callback("asdf");
    }
}

2

Vous avez besoin d'un délégué et d'un rappel. Voici un bel article MSDN qui vous montrera comment utiliser cette technique en C #.


2

Vous pouvez utiliser uniquement le délégué, ce qui est le mieux pour les fonctions de rappel:

public class ServerRequest
{
    public delegate void CallBackFunction(string input);

    public void DoRequest(string request, CallBackFunction callback)
    {
        // do stuff....
        callback(request);
    }
}

et consommez ceci comme ci-dessous:

public class Class1
    {
        private void btn_click(object sender, EventArgs e)
        {
            ServerRequest sr = new ServerRequest();
            var callback = new ServerRequest.CallBackFunction(CallbackFunc);
            sr.DoRequest("myrequest",callback);
        }

        void CallbackFunc(string something)
        {

        }


    }
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.