Passaggio di una funzione di callback a un'altra classe


90

Fondamentalmente sto cercando di passare un metodo a un'altra classe per essere chiamato in seguito, ma non riesco a capirlo in C # (sono ancora troppo abituato a 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)
    {
    }
}

Quindi in seguito voglio che la mia classe ServerRequest attivi fondamentalmente la funzione di callback, non è possibile? (Sto praticamente telefonando a casa a un server per una risposta di accesso al mio software)

Non sono stato in grado di trovare un modo per farlo con i delegati, ricevo continuamente errori. Ecco l'altra classe:

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

È possibile in #? In Objective-C questo sarebbe semplice e farei qualcosa di simile

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

Risposte:


139

Puoi passarlo come Action<string>- il che significa che è un metodo con un singolo parametro di tipo stringche non restituisce nulla (void):

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

E come si chiama DoRequest? Passi una stringa o un metodo?
Kokodoko

1
per altri curiosi di Action. ecco un suggerimento veloce. può avere più parametri di tipo ma nessun ritorno (solo per il passaggio di membri c # Action <type1, .., typeN> non consente modificatori sui tipi Per passare la funzione, utilizzare di nuovo Func <typeList> nessun modificatore su alcun tipo l'ultimo tipo nella list è il tipo di ritorno della funzione in realtà Action e Func sono un modo rapido per utilizzare delegati semplici
gg89

Rendi la mia giornata semplice e pulita!
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

Devi prima dichiarare il tipo di delegato perché i delegati sono fortemente tipizzati:

public void MyCallbackDelegate( string str );

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

Questa è un'ottima soluzione se utilizzi la stessa firma del metodo in molti punti del codice.
mtmurdock

4
È buona norma controllare sempre se il metodo di callback non è nullo prima di chiamarlo.
Maciej

4

Delegateè solo la classe base, quindi non puoi usarla in questo modo. Potresti fare qualcosa del genere però:

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

2
Func<string>sarebbe un metodo che restituisce una stringa - è necessario unAction<string>
BrokenGlass

@BrokenGlass hai ragione mio male - aggiornato (ho + 1d la tua risposta)
Robbie

3

Puoi cambiare il tuo codice in questo modo:

public delegate void CallbackHandler(string str);

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

2

Ciò di cui hai bisogno è un delegato e una richiamata. Ecco un bell'articolo di MSDN che ti mostrerà come usare questa tecnica in C #.


2

È possibile utilizzare solo delegate che è il migliore per le funzioni di callback:

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

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

e consumalo come di seguito:

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)
        {

        }


    }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.