Przekazywanie funkcji zwrotnej do innej klasy


91

Zasadniczo próbuję przekazać metodę do innej klasy, która ma zostać wywołana później, ale nie mogę tego zrozumieć w C # (nadal jestem zbyt przyzwyczajony do 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)
    {
    }
}

Później chcę, aby moja klasa ServerRequest zasadniczo uruchamiała funkcję wywołania zwrotnego, czy nie jest to możliwe? (Zasadniczo dzwonię do domu na serwer w celu uzyskania odpowiedzi logowania do mojego oprogramowania)

Nie byłem w stanie znaleźć sposobu, aby to zrobić z delegatami, ciągle otrzymuję błędy. Oto druga klasa:

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

Czy to możliwe w #? W Objective-C byłoby to proste i po prostu zrobiłbym coś takiego

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

Odpowiedzi:


140

Możesz przekazać to jako Action<string>- co oznacza, że ​​jest to metoda z jednym parametrem typu, stringktóry nic nie zwraca (void):

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

A jak nazywasz DoRequest? Czy przekazujesz ciąg znaków czy metodę?
Kokodoko

1
dla innych ciekawych Akcji. oto krótka wskazówka. może mieć wiele parametrów typu, ale nie zwraca (do przekazywania tylko składowych C # Action <type1, .., typeN> nie zezwala na modyfikator typów Aby przekazać funkcję, użyj ponownie Func <typeList> bez modyfikatora na żadnym typie ostatni typ w lista jest zwracanym typem funkcji w rzeczywistości Action i Func to szybki sposób na użycie prostych delegatów
gg89

Niech mój dzień będzie prosty i czysty!
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

Musisz najpierw zadeklarować typ delegata, ponieważ delegaci są silnie wpisani:

public void MyCallbackDelegate( string str );

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

To świetne rozwiązanie, jeśli używasz tej samej metody podpisu w wielu miejscach w kodzie.
mtmurdock

4
Dobrą praktyką jest zawsze sprawdzanie, czy metoda wywołania zwrotnego nie ma wartości NULL przed jej wywołaniem.
Maciej

4

Delegatejest tylko klasą bazową, więc nie możesz jej tak używać. Możesz jednak zrobić coś takiego:

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

2
Func<string>byłaby metodą, która zwraca łańcuch - potrzebujeszAction<string>
BrokenGlass

@BrokenGlass masz rację mój zły - zaktualizowana (mam + 1d odpowiedź)
Robbie

4

Możesz zmienić swój kod w ten sposób:

public delegate void CallbackHandler(string str);

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

2

Potrzebujesz pełnomocnika i oddzwonienia. Oto ładny artykuł MSDN, który pokaże, jak używać tej techniki w C #.


2

Możesz użyć tylko delegata, który jest najlepszy dla funkcji zwrotnych:

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

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

i konsumuj to jak poniżej:

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

        }


    }
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.