การส่งผ่านฟังก์ชันการโทรกลับไปยังคลาสอื่น


92

โดยพื้นฐานแล้วฉันพยายามส่งเมธอดไปยังคลาสอื่นเพื่อเรียกใช้ในภายหลัง แต่ไม่สามารถเข้าใจสิ่งนี้ได้ใน 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];

คำตอบ:


143

คุณสามารถส่งเป็นAction<string>- ซึ่งหมายความว่าเป็นวิธีการที่มีพารามิเตอร์ประเภทเดียวstringที่ไม่ส่งคืนอะไรเลย (โมฆะ):

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

และเรียก DoRequest อย่างไร? คุณส่งสตริงหรือวิธีการ?
Kokodoko

1
สำหรับคนอื่น ๆ ที่อยากรู้อยากเห็นเกี่ยวกับ Action นี่คือเคล็ดลับสั้น ๆ สามารถมี parms หลายประเภท แต่ไม่ส่งคืน (สำหรับการส่งสมาชิก 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

6
เป็นแนวทางปฏิบัติที่ดีในการตรวจสอบเสมอว่าวิธีการโทรกลับไม่เป็นโมฆะก่อนที่จะเรียกใช้
Maciej

4

Delegateเป็นเพียงคลาสพื้นฐานดังนั้นคุณจึงไม่สามารถใช้แบบนั้นได้ คุณสามารถทำสิ่งนี้ได้แม้ว่า:

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

2
Func<string>จะเป็นวิธีที่ส่งคืนสตริง - คุณต้องมีAction<string>
BrokenGlass

@BrokenGlass คุณถูกต้องของฉันไม่ดี - อัปเดต (ฉัน + 1d คำตอบของคุณ)
Robbie

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

        }


    }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.