Truyền một hàm gọi lại cho một lớp khác


90

Về cơ bản, tôi đang cố gắng chuyển một phương thức cho một lớp khác sẽ được gọi sau này, nhưng không thể hiểu được điều này trong C # (tôi vẫn quá quen với 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)
    {
    }
}

Sau đó, tôi muốn lớp ServerRequest của mình về cơ bản kích hoạt hàm gọi lại, điều này không thể thực hiện được? (Về cơ bản, tôi đang gọi điện về nhà đến máy chủ để nhận phản hồi đăng nhập vào phần mềm của mình)

Tôi đã không thể tìm ra cách để làm điều này với các đại biểu, liên tục nhận được lỗi. Đây là lớp khác:

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

Điều này có khả thi trong # không? Trong Objective-C, điều này sẽ đơn giản và tôi chỉ làm điều gì đó như

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

Câu trả lời:


139

Bạn có thể chuyển nó dưới dạng Action<string>- có nghĩa là nó là một phương thức với một tham số duy nhất của kiểu stringkhông trả về bất kỳ thứ gì (void):

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

Và bạn gọi DoRequest như thế nào? Bạn có truyền một chuỗi hay một phương thức không?
— Kokodoko

1
cho những người tò mò khác về Hành động. đây là một mẹo nhanh. nó có thể có nhiều parms kiểu nhưng không có trả về (chỉ để chuyển các thành viên c # Action <type1, .., typeN> không cho phép sửa đổi trên các loại danh sách là loại chức năng trở lại thực sự hành động và Func là cách nhanh chóng để sử dụng các đại biểu đơn giản
— gg89

Làm cho ngày của tôi, đơn giản và sạch sẽ!
— 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

Trước tiên, bạn phải khai báo kiểu của người được ủy quyền vì người được nhập rất mạnh:

public void MyCallbackDelegate( string str );

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

Đây là một giải pháp tuyệt vời nếu bạn đang sử dụng cùng một chữ ký phương pháp ở nhiều vị trí trong mã của mình.
— mtmurdock

4
Một phương pháp hay là luôn kiểm tra xem phương thức gọi lại có phải là null hay không trước khi gọi nó.
— Maciej

4

Delegatechỉ là lớp cơ sở nên bạn không thể sử dụng nó như vậy. Bạn có thể làm điều gì đó như sau:

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

2
Func<string>sẽ là một phương pháp mà trả về một chuỗi - bạn cần mộtAction<string>
— BrokenGlass

@BrokenGlass, bạn nói đúng, tôi không ổn - đã cập nhật (tôi đã +1 câu trả lời của bạn)
— Robbie

3

Bạn có thể thay đổi mã của mình theo cách này:

public delegate void CallbackHandler(string str);

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

2

Những gì bạn cần là một đại biểu và một cuộc gọi lại. Đây là một bài viết hay về MSDN sẽ hướng dẫn bạn cách sử dụng kỹ thuật này trong C #.


2

Bạn chỉ có thể sử dụng ủy quyền tốt nhất cho các hàm gọi lại:

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

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

và tiêu thụ như sau:

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

        }


    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookie và Chính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.