Passar uma função de retorno de chamada para outra classe


90

Basicamente, estou tentando passar um método para outra classe para ser chamado mais tarde, mas não consigo descobrir isso em C # (ainda estou acostumado com 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)
    {
    }
}

Posteriormente, quero que minha classe ServerRequest basicamente dispare a função de retorno de chamada, isso não é possível? (Estou basicamente ligando para um servidor para obter uma resposta de login no meu software)

Não consegui encontrar uma maneira de fazer isso com os delegados, obter erros continuamente. Aqui está a outra classe:

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

Isso é possível em #? Em Objective-C isso seria simples e eu faria algo como

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

Respostas:


139

Você pode passá-lo como Action<string>- o que significa que é um método com um único parâmetro do tipo stringque não retorna nada (void):

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

E como você chama DoRequest? Você passa uma string ou um método?
Kokodoko

1
para outros curiosos sobre a ação. aqui está uma dica rápida. ele pode ter vários parâmetros de tipo, mas nenhum retorno (para passar membros c # somente Ação <type1, .., typeN> não permite modificador em tipos Para passar função, use Func <typeList> novamente nenhum modificador em qualquer tipo o último tipo no list é o tipo de retorno de função, na verdade, Action e Func são uma maneira rápida de usar delegados simples
gg89

Torne o meu dia simples e limpo!
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

Você deve primeiro declarar o tipo de delegado porque os delegados são fortemente tipados:

public void MyCallbackDelegate( string str );

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

Esta é uma ótima solução se você estiver usando a mesma assinatura de método em muitos lugares em seu código.
mtmurdock,

4
É uma boa prática sempre verificar se o método de retorno de chamada não é nulo antes de chamá-lo.
Maciej

4

Delegateé apenas a classe base, então você não pode usá-la assim. Você poderia fazer algo assim:

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

2
Func<string>seria um método que retorna uma string - você precisa de umAction<string>
BrokenGlass

@BrokenGlass você está certo, meu mal - atualizado (eu + 1d sua resposta)
Robbie

3

Você pode alterar seu código desta forma:

public delegate void CallbackHandler(string str);

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

2

O que você precisa é de um delegado e um retorno de chamada. Aqui está um bom artigo do MSDN que mostrará como usar essa técnica em C #.


2

Você pode usar apenas delegado, o que é melhor para funções de retorno de chamada:

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

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

e consuma como abaixo:

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

        }


    }
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.