.NET 回调、接口回调、 委托

回调浅析(委托、接口回调)
说到C#回调,通常情况下,指的是某个委托或者接口回调。现将从网上各位前辈那里学得的一些经验加以整理,形成一个稍全面一些的文章,希望对大家有所帮助!
一、 委托
》》委托5步法

  1. 声明委托:确定返回值、参数 不能用Static修饰的,因为声明委托相当于数据类型,推荐声明隶属命名空间下。不用隶属某个类下
  2. 创建委托对象: 哪里调用就在那里创建 , 这里可以创建静态委托对象 static 声明的委托 【因为具体的方法,靠委托去间接执行的】
  3. 创建委托方法: 哪里执行在哪里创建
  4. 绑定委托: 哪里执行在哪里创建
  5. 调用委托:

在这里插入图片描述

注意:
如果 在窗体【或类】声明的委托,属于这个窗体【类】,不属于它的实例对象 相当于 静态效果

public partial class Form1 : Form
    {
        public  delegate   void Fn(string inf);
        public Form1()
        {
            InitializeComponent();
        }
    }

//------------------------------------
 public partial class Form2 : Form
    {
        public void  f1(string s)
        {
        }
        public Form2()
        {
            InitializeComponent();

            Form1.Fn s =f1;
           
        }
    }

先看一段代码:
// 定义委托
delegate void WorkDone();

class Program
{
static void Main(string[] args)
{
Do();

	Console.ReadLine();
}

public static void Do()
{
	// 首先给callback委托赋值
	WorkDone callback = new WorkDone(WorkDoneHandler);
	 //WorkDone callback = WorkDoneHandler;   等价  简写
	
	// 将callback作为参数
	Working(callback);
}

public static void Working(WorkDone callBack)
{
	// 当工作完成的时候执行这个委托
	callBack();
}

public static void WorkDoneHandler()
{
	Console.WriteLine(DateTime.Now);
}

}

上面的代码中,将方法WorkDoneHandler()作为参数,传递给了另一个方法Working(WorkDone callBack),这样做的好处在于,可以动态的指定执行哪个方法。比如在Do()方法中,我们指定的callback 是WorkDoneHandler 当然也可以是其它匹配的方法。而Working()方法根本不需要知道自己最后执行的是哪个Handler。
二、 接口回调
通常情况下,我们创建一个对象,并马上直接去使用它的方法。然而,在有些情况下,希望能在某个场景出现后或条件满足时才调用此对象的方法。回调就可以解决这个“延迟调用对象方法”的问题。这个被调用方法的对象称为回调对象。
实现回调的原理简介如下:
首先创建一个回调对象,然后再创建一个控制器对象,将回调对象需要被调用的方法告诉控制器对象。控制器对象负责检查某个场景是否出现或某个条件是否满足。当此场景出现或此条件满足时,自动调用回调对象的方法。
//----------------------------
TestMulticastDelegate tmd = new TestMulticastDelegate (PrintMessage1);
tmd += new TestMulticastDelegate (PrintMessage2);
tmd +=new TestMulticastDelegate ( PrintMessage3);

等价简写
TestMulticastDelegate tmd = PrintMessage1;
tmd += PrintMessage2;
tmd +=PrintMessage3;

最后,我们要用一种比较复杂的方法来写,但是却是链式委托的核心所在:

TestMulticastDelegate tmd1 = new TestMulticastDelegate(PrintMessage1);
TestMulticastDelegate tmd2 = new TestMulticastDelegate(PrintMessage2);
TestMulticastDelegate tmd3 = new TestMulticastDelegate(PrintMessage3);
// 核心本质:将三个委托串联起来 委托组合
TestMulticastDelegate tmd = tmd1 + tmd2 + tmd3;
tmd.Invoke(); // 显式调用Invoke方法来调用委托 同步的,beginInvoke异步
tmd();// 隐式调用委托
我们在实际开发中经常使用第二种方法,但是却不能不了解方法三,它是链式委托的本质所在。
//---------------------------------
以下为C#实现回调的一个小例子:
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
//创建一个控制器对象,将提供给它的回调对象传入
Controller obj = new Controller(new CallBack());
//启动
obj.Star();
}
}
public interface IBack
{
void run();
}
public class CallBack : IBack
{
public void run()
{
//为了简洁这里只是显示下时间
System.Console.WriteLine(DateTime.Now);
}
}
public class Controller
{
public IBack CallBackObj = null; //这里引用回调对象
public Controller(IBack obj)
{
this.CallBackObj = obj;
}
public void Star()
{
Console.WriteLine(“敲键盘任意键就显示当前的时间,直到按ESC退出…”);
while (Console.ReadKey(true).Key != ConsoleKey.Escape)
{
CallBackObj.run();
}
}
}
}
可以看到,当示例程序运行时,何时调用CallBack对象的run()方法是由用户决定的,用户每敲一个键,控制器对象就调用一次CallBack的run()方法。这个示例中实现回凋的关键在于IBack接口的引入。

 如果不用IBack接口,而直接使用 CallBack对象,一样可以实现同样的效果,如下: 
   public class Controller 
 { 
     public CallBack CallBackObj = null;   //回调对象方法的引用 
     public Controller(CallBack obj) 
     { 
         this.CallBackObj = obj; 
     } 
     public void Star() 
     { 
         Console.WriteLine("敲键盘任意键就显示当前的时间,直到按ESC退出...."); 
         while (Console.ReadKey(true).Key != ConsoleKey.Escape) 
         { 
             CallBackObj.run(); 
         } 
     } 
 } 

但仔细思考,这样做的结果就使Controller类与CallBack对象绑定在一起,万一如果需要调用其他类型的对象,则必须修改Controller类的代码。
如果Controller类接收的是一个抽象的接口变量Iback,则任何实现了该接口的对象都可以被Controller类对象所回调,Controller类的代码就再不用被修改,保证了代码对环境的适应性,无疑是一个很好的解决方案。

在这里插入图片描述
委托的方法既可以是无返回值的,也可以是有返回值的,但如果多一个带返回值的方法被添加到委托链中时,我们需要手动地调用委托链上的每个方法,否则只能得到委托链上最后被调用的方法的返回值。
foreach (var del in 委托对象.GetInvocationList())
{
Console.WriteLine(del.DynamicInvoke());
}
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值