Передача функции обратного вызова другому классу


91

Я в основном пытаюсь передать метод другому классу, который будет вызван позже, но не могу понять этого на C # (я все еще слишком привык к 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)
    {
    }
}

Позже я хочу, чтобы мой класс ServerRequest в основном запускал функцию обратного вызова, разве это невозможно? (Я в основном звоню домой на сервер для ответа на вход в мое программное обеспечение)

Я не смог найти способ сделать это с делегатами, постоянно получаю ошибки. Вот другой класс:

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

Возможно ли это в #? В Objective-C это было бы просто, и я бы просто сделал что-то вроде

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

Ответы:


140

Вы можете передать его как Action<string>- что означает, что это метод с одним параметром типа, stringкоторый ничего не возвращает (void):

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

А как вы вызываете DoRequest? Вы передаете строку или метод?
— Kokodoko,

1
для других, интересующихся Action. вот небольшой совет. он может иметь несколько параметров типа, но не возвращать (для передачи только членов C # Action <type1, .., typeN> не разрешает модификатор для типов Чтобы передать функцию, снова используйте Func <typeList> без модификатора для любого типа последний тип в list - это тип, возвращаемый функцией, на самом деле Action и Func - быстрый способ использования простых делегатов
— gg89

Сделай мой день простым и чистым!
— 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

Вы должны сначала объявить тип делегата, потому что делегаты строго типизированы:

public void MyCallbackDelegate( string str );

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

Это отличное решение, если вы используете одну и ту же сигнатуру метода во многих местах своего кода.
— mtmurdock

4
Перед его вызовом рекомендуется всегда проверять, не является ли метод обратного вызова нулевым.
— Maciej

4

Delegateэто просто базовый класс, поэтому вы не можете его так использовать. Вы могли бы сделать что-то вроде этого:

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

2
Func<string>будет методом, возвращающим строку - вам понадобитсяAction<string>
— BrokenGlass

@BrokenGlass, ты прав, мое плохое - обновлено (я добавил +1 к твоему ответу)
— Робби

4

Вы можете изменить свой код таким образом:

public delegate void CallbackHandler(string str);

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

2

Что вам нужно, так это делегат и обратный вызов. Вот хорошая статья MSDN, которая покажет вам, как использовать эту технику на C #.


2

Вы можете использовать только делегат, который лучше всего подходит для функций обратного вызова:

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

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

и потребляйте это, как показано ниже:

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

        }


    }
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.