`
cdragon
  • 浏览: 78322 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

关于“回调”的实现

阅读更多

callback基础:

回调机制包括带委托的成员、虚拟化的成员、基于接口的插件。事件是回调最常用的形式,当事件raised时,调用绑定方法的事件句柄的实例。

 

在编程机制或函数调用模式上,一般分成三种,同步调用、回调和异步调用。回调在不同的语言中有不同实现。具体在C#中,是使用以C为基础的语言环境特有的委托来实现回调,而通过AsyncCallback亦可实现异步调用。委托是实现调用者与被调用实例间解耦(decoupling)的工具。

 

delegate定义:

委托类型由四个成员组成,编译器会自动提供一个这样的完整类,包括:constructor,Invoke方法,BeginInvoke方法和EndInvoke方法。

 

与委托一切相关的本质:

F(f)  即函数的函数,其中f经抽象为委托,变形为F(delegate);F进一步抽象为处理,最后为handler(delegate)。MS为函数代理专门制造出了委托概念,带有浓重的人为斧凿痕迹,这样大的代价,必定有MS的理由吧。

 

下面我们以静态函数为例,论述一下它的原理: 

1、将彼此具有相同结构的函数(如函数Fa和Fb,)归为(classify)一个类别,类型(type)为引用类型;经过语言封装,赋予一个标识,就叫作"delegate"吧;

 

2、对具体执行函数Fa或Fb进行调用:用某处理函数F封装对Fa或Fb的处理,以"delegate"(即同构函数的指针-以"某个delegate"作为代名词)作参,传递给该函数;在F中对该"delegate"进行处理(这里的函数F是一个重要的'proxy').

public delegate void EnumConnectionsCallback(DBConnection connection);
public void EnumConnections(EnumConnectionsCallback callback)
{
  foreach (DBConnection connection in activeConnections)
  {
        
    callback(connection);
     //上句,系统默认自动调用callback.Invoke(connection)
  }
 }

 

 

 3、接下来,定义该同构函数("delegate")的某具体函数的行为,以便在上述封装中进行反向调用。

 

  4、于客户端实例化委托。通过以上步骤,能够将所有使用相同结构(数字签名)的函数,映射到某个"delegate"并由系统自动处理细节,但函数行为可以完全不同。

小结: 我们看到委托实现回调,基本可归纳为这样几个步骤,来达到解耦:

(1)定义头(header)--委托 

(2)定义实际caller

(3)定义具体处理--函数

如果把函数理解为特定函数如EventHandler(object sender,EventArgs e),那么以上也就是事件类型的原型,所以,事件是对内置委托、EventHandler处理函数、环境参数(context argument=EventArgs)的(publisher-subscriber pattern)封装,可直接使用。(关于事件类型的详细分析

  

完整的原型用例:

 

using System;
using System.Collections;

class DBConnection
{
    protected static int NextConnectionNbr = 1;

    protected string connectionName;
    public string ConnectionName
    {
        get
        {
            return connectionName;
        }
    }

    public DBConnection()
    {
        connectionName = "Database Connection " 
            + DBConnection.NextConnectionNbr++;
    }
}

class DBManager
{
    protected ArrayList activeConnections;
    public DBManager()
    {
        activeConnections = new ArrayList();
        for (int i = 1; i < 6; i++)
        {
            activeConnections.Add(new DBConnection());
        }
    }

    public delegate void EnumConnectionsCallback(DBConnection connection);
    public void EnumConnections(EnumConnectionsCallback callback)
    {
        foreach (DBConnection connection in activeConnections)
        {
            callback(connection);
        }
    }
};

 

class InstanceDelegate
{
    public static void PrintConnections(DBConnection connection)
    {
        Console.WriteLine("[InstanceDelegate.PrintConnections] {0}",
            connection.ConnectionName);
    }

    public static void Main()
    {
        DBManager dbManager = new DBManager();

        Console.WriteLine("[Main] Instantiating the " +
            "delegate method");
          DBManager.EnumConnectionsCallback _printConnections =
             new DBManager.EnumConnectionsCallback(PrintConnections);

        Console.WriteLine("[Main] Calling EnumConnections " +
            "- passing the delegate");
          dbManager.EnumConnections(_printConnections);

        Console.ReadLine();
    }
};

小结: 委托其实是C#中,对同构函数进行抽象的语法糖(OOP),也可称为对方法进行引用的类型。

 

下面我们对委托“原型”进行初步简化。能进行这种简化的原因是“委托推断(delegate inference)”,即系统自动创建委托对象。

 

using System;
using System.Collections;

class DBConnection
{
    protected static int NextConnectionNbr = 1;

    protected string connectionName;
    public string ConnectionName
    {
        get
        {
            return connectionName;
        }
    }

    public DBConnection()
    {
        connectionName = "Database Connection " 
            + DBConnection.NextConnectionNbr++;
    }
}

class DBManager
{
    protected ArrayList activeConnections;
    public DBManager()
    {
        activeConnections = new ArrayList();
        for (int i = 1; i < 6; i++)
        {
            activeConnections.Add(new DBConnection());
        }
    }

    public delegate void EnumConnectionsCallback(DBConnection connection);
    public void EnumConnections(EnumConnectionsCallback callback)
    {
        foreach (DBConnection connection in activeConnections)
        {
            callback(connection);
        }
    }
};

class InstanceDelegate
{
    public static void PrintConnections(DBConnection connection)
    {
        Console.WriteLine("[InstanceDelegate.PrintConnections] {0}",
            connection.ConnectionName);
    }

    public static void Main()
    {
        DBManager dbManager = new DBManager();

        Console.WriteLine("[Main] Instantiating the " +
            "delegate method");

/*          DBManager.EnumConnectionsCallback _printConnections =
             new DBManager.EnumConnectionsCallback(PrintConnections);*/
            //使用委托推断,直接赋予实例化的委托以函数名称
        DBManager.EnumConnectionsCallback _printConnections = PrintConnections;

        Console.WriteLine("[Main] Calling EnumConnections " +
            "- passing the delegate");
          dbManager.EnumConnections(_printConnections);

        Console.ReadLine();
    }
};

  

总结:利用委托实现回调时,虽语法繁琐,但效率颇高。C#终究是一种强类型的语言,有代价是正常。而我们可以通过“委托推断”等"shortcut"措施对其语法进行简化。

 

委托本质上是对函数的一种归集和反射实现;而事件是组件间通用的消息类型,也是组件关系解耦的模型。

 

  • 大小: 271.3 KB
分享到:
评论

相关推荐

    java 回调函数 实现

    2. **回调函数的实现**:在描述中提到,回调函数是通过自己模拟实现的。这通常意味着创建一个接口,并在需要回调的地方,如按钮点击事件,实现该接口。例如,`Button.java`类可能会有一个`setClickListener`方法,...

    JNA 回调 范例 C++异步回调实现

    找了下资料,居然没有回调函数的样例,郁闷的我不行,于是就自己折腾一晚上,自己实现一个。 C++部分使用ACE实现了一个线程,线程中调用Java部分的回调函数。 C++使用vc8开发,代码跨平台,不过偷懒,没写makefile...

    C# 实现回调函数

    接下来,我们将深入探讨C#中实现回调函数的原理、方式以及应用场景。 首先,我们需要理解什么是回调函数。回调函数本质上就是一个函数引用,可以在其他函数执行过程中或结束后被调用。在C#中,你可以通过几种方式来...

    java实现企业微信回调配置案例

    本案例将详细讲解如何使用Java来实现企业微信的回调配置,并提供相关的工具代码示例。 1. **企业微信API介绍** 企业微信提供了丰富的API接口,包括但不限于用户管理、部门管理、消息推送等。回调配置主要是通过...

    mfc下实现回调函数

    打开这个项目,你可以看到具体的代码实现,包括如何定义回调函数、如何在消息映射中声明、如何设置和调用回调,以及如何传递和处理用户数据。 通过以上步骤,你可以了解在MFC中实现回调函数的基本流程。回调函数在...

    客户端无刷新回调,ICallBackEverHandler实现客户端回调

    总结起来,`ICallBackEverHandler`可能是一个自定义的.NET回调处理接口,用于实现客户端无刷新回调。通过这种方式,可以创建更加流畅、响应式的Web应用,提高用户体验,尤其是在需要实时验证或更新数据的场景下。

    回调机制的实现,主要介绍回调机制的实现过程

    本文将深入探讨回调机制的实现,特别是如何在C和C++中实现回调。 首先,让我们回顾一下回调的主要用途: 1. 发出通知,但不关心接收者身份:在这种情况下,回调函数作为一个通知机制,用来传递信息,而无需知道...

    c++调用dll,实现消息回调

    以上就是关于C++调用DLL并实现消息回调的核心概念和步骤。在实际开发中,还需要考虑错误处理、内存管理以及跨平台兼容性等问题。正确理解和运用这些知识,可以帮助我们有效地利用DLL来扩展和优化C++应用程序。

    回调简单实现

    回调在编程中是一种常见且重要的概念,特别是在异步编程中,它是处理任务间依赖关系、控制流程的关键机制。本文将详细解析回调的定义、工作原理,并通过提供的`callbackDemo`示例来帮助新手深入理解这一概念。 ### ...

    使用C语言写的回调函数

    下面将详细阐述回调函数的概念、实现方式以及在C语言中的应用。 **1. 回调函数概念** 回调函数是一种设计模式,它使得调用者能够将一个函数作为参数传递给其他函数,由被调用者在执行完某些操作后或者在特定事件...

    [iOS]Objective-C利用协议实现回调函数(类似java的回调函数)

    在标题提及的“[iOS]Objective-C利用协议实现回调函数(类似java的回调函数)”中,我们主要讨论的是Objective-C如何通过协议(Protocol)来实现类似于Java中的回调函数功能。这种机制对于异步编程、事件处理以及...

    非托管代码回调方法的实现

    非托管代码回调方法的实现是将托管代码与非托管代码(如C++或原生DLL)集成的关键技术。在.NET框架中,托管代码是由CLR(Common Language Runtime)管理的,而非托管代码则不受其控制。当需要从非托管代码调用托管...

    c#线程结束后,实现的委托回调函数源码

    本篇将深入探讨如何在C#中实现线程结束后的委托回调功能,并安全地访问主线程中的控件。 首先,理解线程和委托的概念至关重要。线程是程序执行的流程,每个进程至少有一个线程。委托是C#中的一种类型,它类似于函数...

    Java利用接口实现回调

    在Java支持方法指针之前,Java接口不能提供一种实现回调的好方法。如果您习惯于传递在事件驱动编程模型中调用的函数指针,则您会喜欢本技巧。  熟悉MS-Windows和X Window System事件驱动编程模型的开发人员,习惯...

    易语言实现 c++dll的消息回调函数

    易语言实现 c++dll的消息回调函数

    易语言类方法回调

    在易语言中,实现类方法回调通常需要以下步骤: 1. **定义类和方法**:首先,你需要定义一个类,并在其中声明你要回调的方法。例如,你可以有如下的类定义: ```易语言 .类 基类 .常量 句柄 .过程 .方法1() ....

    接口回调实现简易购物车功能

    在本示例中,“接口回调实现简易购物车功能”着重展示了如何利用接口回调来构建一个简单的购物车系统。下面将详细阐述接口回调的基本概念、其在购物车功能中的应用以及实现过程。 接口回调的核心在于定义一个接口,...

    在 ASP.NET 网页中实现回调

    为了支持回调,页面或用户控件需要实现 ICallbackEventHandler 接口。对于单文件页或用户控件,可以在页面指令中声明 `@Implements` 指令,如以下示例所示: - Visual Basic: ```vbnet ``` - C#: ```csharp ```...

    C#回调函数

    4. **线程间通信**:在多线程环境中,线程A可能需要在完成某项任务后通知线程B,这时可以使用回调函数来实现线程间的通信。 下面是一个简单的回调函数示例,演示如何在C#中使用委托和回调: ```csharp using ...

    回调函数实现控制上下左右

    在这个特定的场景中,标题"回调函数实现控制上下左右"表明我们要讨论如何利用回调函数来处理键盘输入,从而控制一个对象(可能是游戏中的角色或其他类型的应用程序元素)在四个基本方向上移动:上、下、左、右。...

Global site tag (gtag.js) - Google Analytics