首页 > 其他分享 >无涯教程-F# - 事件类型

无涯教程-F# - 事件类型

时间:2023-11-29 20:05:38浏览次数:33  
标签:触发 教程 name shift 无涯 let IEvent 类型 事件

事件允许类之间相互发送和接收消息,对象通过同步消息传递相互通信。

事件类和事件模块

Control.Event <'T>类有助于创建可观察的对象或事件。

Member 说明
Publish 将观察输出作为一等值发布。
Trigger 使用给定的参数触发观察。

Control.Event模块提供用于管理事件流的功能-

Value 描述
add : ('T → unit) → Event<'Del,'T> → unit 每次触发给定事件时运行给定函数。
choose : ('T → 'U option) → IEvent<'Del,'T> → IEvent<'U> 返回一个新事件,该事件在从原始事件中选择的消息上触发。选择功能将原始消息带到可选的新消息中。
filter : ('T → bool) → IEvent<'Del,'T> → IEvent<'T> 返回一个新事件,该事件侦听原始事件并仅在事件的参数传递给定函数时才触发结果事件。
map : ('T → 'U) → IEvent<'Del, 'T> → IEvent<'U> 返回一个新事件,该事件传递由给定函数转换的值。
merge : IEvent<'Del1,'T> → IEvent<'Del2,'T> → IEvent<'T> 当任一输入事件触发时,触发输出事件。
pairwise : IEvent<'Del,'T> → IEvent<'T * 'T> 返回一个新事件,该事件在输入事件的第二次和后续触发时触发。输入事件的第N次触发将成对的第N-1次触发和第N次触发的参数传递。传递给第N-1次触发的参数将保持隐藏的内部状态,直到发生第N次触发为止。
partition : ('T → bool) → IEvent<'Del,'T> → IEvent<'T> * IEvent<'T> 如果谓词对事件参数的应用返回true,则返回侦听原始事件并触发第一个结果事件的新事件,如果第二个事件返回false,则触发新的事件。
scan : ('U → 'T → 'U) → 'U → IEvent<'Del,'T> → IEvent<'U> 返回一个新事件,该事件包括将给定累加函数应用于输入事件上触发的连续值的结果。内部状态项记录状态参数的当前值。在执行累积函数期间,内部状态未锁定,因此应注意不要同时由多个线程触发输入IEvent。
split : ('T → Choice<'U1,'U2>) → IEvent<'Del,'T> → IEvent<'U1> * IEvent<'U2> 如果该函数对事件参数的应用返回了Choice1Of2,则返回一个侦听原始事件并触发第一个结果事件的新事件,如果第二个事件返回Choice2Of2,则触发该事件。

创建事件

事件是通过 Event 类创建和使用的, Event构造函数用于创建事件。

type Worker(name : string, shift : string) =
   let mutable _name = name;
   let mutable _shift = shift;
   let nameChanged = new Event<unit>() (* creates event *)
   let shiftChanged = new Event<unit>() (* creates event *)

   member this.Name
      with get() = _name
      and set(value) = _name <- value

   member this.Shift
      with get() = _shift
      and set(value) = _shift <- value

之后,您需要将nameChanged字段公开为公共成员,以便侦听器可以挂接到该事件,您可以使用事件的 Publish 属性-

type Worker(name : string, shift : string) =
   let mutable _name = name;
   let mutable _shift = shift;

   let nameChanged = new Event<unit>() (* creates event *)
   let shiftChanged = new Event<unit>() (* creates event *)

   member this.NameChanged = nameChanged.Publish (* exposed event handler *)
   member this.ShiftChanged = shiftChanged.Publish (* exposed event handler *)

   member this.Name
      with get() = _name
      and set(value) = _name <- value
      nameChanged.Trigger() (* invokes event handler *)

   member this.Shift
      with get() = _shift
      and set(value) = _shift <- value
   shiftChanged.Trigger() (* invokes event handler *)

接下来,将回调添加到事件处理程序,每个事件处理程序的类型都是IEvent <'T>,它提供了几种方法-

方法 说明
val Add:event :('T→unit)→unit 将侦听器功能连接到事件。事件触发时将调用侦听器。
val AddHandler:'del→unit 将处理程序委托对象连接到事件。以后可以使用RemoveHandler删除处理程序。事件触发时将调用侦听器。
val RemoveHandler:'del→unit 从事件侦听器存储中删除侦听器委托。

以下示例演示了上面讨论的概念和技术-

type Worker(name : string, shift : string) =
   let mutable _name = name;
   let mutable _shift = shift;

   let nameChanged = new Event<unit>() (* creates event *)
   let shiftChanged = new Event<unit>() (* creates event *)

   member this.NameChanged = nameChanged.Publish (* exposed event handler *)
   member this.ShiftChanged = shiftChanged.Publish (* exposed event handler *)

   member this.Name
      with get() = _name
      and set(value) = 
         _name <- value
         nameChanged.Trigger() (* invokes event handler *)

   member this.Shift
      with get() = _shift
      and set(value) = 
         _shift <- value
         shiftChanged.Trigger() (* invokes event handler *)

let wk = new Worker("Wilson", "Evening")
wk.NameChanged.Add(fun () -> printfn "Worker changed name! New name: %s" wk.Name)
wk.Name <- "William"
wk.NameChanged.Add(fun () -> printfn "-- Another handler attached to NameChanged!")
wk.Name <- "Bill"

wk.ShiftChanged.Add(fun () -> printfn "Worker changed shift! New shift: %s" wk.Shift)
wk.Shift <- "Morning"
wk.ShiftChanged.Add(fun () -> printfn "-- Another handler attached to ShiftChanged!")
wk.Shift <- "Night"

编译并执行程序时,将产生以下输出-

Worker changed name! New name: William
Worker changed name! New name: Bill
-- Another handler attached to NameChanged!
Worker changed shift! New shift: Morning
Worker changed shift! New shift: Night
-- Another handler attached to ShiftChanged!

参考链接

https://www.learnfk.com/fsharp/fsharp-events.html

标签:触发,教程,name,shift,无涯,let,IEvent,类型,事件
From: https://blog.51cto.com/u_14033984/8619886

相关文章

  • 无涯教程-F# - 模块声明
    F#模块是F#代码构造的组合,如类型,值,函数值和do绑定中的代码,它被实现为仅具有静态成员的公共语言运行时(CLR)类。根据情况,整个文件是否包含在模块中,有两种类型的模块声明-顶级模块声明本地模块声明在顶层模块声明中,整个文件都包含在模块中,在这种情况下,文件中的第一个声明是模块......
  • [TS手册学习] 01_基础、常见类型与概念
    TS官方Handbook:TypeScript:Handbook-TheTypeScriptHandbook(typescriptlang.org)基础相关概念运行时错误:JS的大多数错误都只能在运行的过程中被发现。静态类型系统:TS可以在运行代码之前发现错误。非异常失败:例如在JS中访问一个对象不存在的属性,不会导致......
  • 【Python入门教程】Python的shutil库介绍+基础函数使用(文件/目录复制、移动、删除、解
    ​前言        很多时候编过的代码过段时间就忘了,所以想用博文记录一下一些平时常用库的函数,今天跟大家分享一下python的shutil库的常用函数,包括文件复制、删除、移动等常见操作。同时为了复习之前python类的使用,所以今天的代码就用类封装起来了,大家直接看函数就行,不需......
  • Gitee - 基于 Git 的代码托管和研发协作平台本地代码同步教程
    什么是Gitee?一、Gitee的发展史。Gitee(码云)是开源中国于2013年推出的基于Git的代码托管平台、企业级研发效能平台,提供中国本土化的代码托管服务。二、个人对Gitee的理解Gitee跟Git有什么区别,个人认为一个是国内、一个是国外,但是两个的目的都是一样的,都是为了方便彼此更好的代......
  • go数据类型-sync.map
    定义在runtime的sync.map包中有定义:typeMapstruct{ muMutex//锁 readatomic.Pointer[readOnly]//包含了readOnly类型的一个struct,下方把Pointer也贴了 dirtymap[any]*entry //一个map存储数据 missesint//错过、没有命中}//readOnlyisanim......
  • 基本数据类型-C语言-2023/11/29
    ......
  • 运维初级实践——Linux系统命令教程
    区块链运维工程师在Linux环境中常用的命令、快捷键,以及安装软件和文件管理的最佳实践。1.常用Linux命令1.1文件和目录操作ls:列出目录内容cd:更改目录mkdir:创建新目录rm:删除文件或目录cp:复制文件或目录mv:移动或重命名文件或目录#列出当前目录的内容ls......
  • 关于人机界面的定义/类型/开发/优缺点及应用
    在本文中,数维图小编将为您介绍HMI的定义、HMI的类型、HMI的选择、HMI的优缺点。什么是HMI? 人机界面简称HMI,是一种允许人类从控制制造过程的PLC发出指令和接收反馈的设备。换句话说,它是将人连接到机器、系统或设备的用户界面或仪表板。虽然从技术上讲,该术语可以应用于允许......
  • java Date类型数据如何比较大小
    ......
  • 关于Python类型注解的几个实用小技巧
    虽然python是动态类型语言,但是python3.5引入的类型注解特性却很有用.不但有助于源码阅读,而且在类型提示和代码自动补全上也很方便.但是它毕竟不是静态类型编译型语言,有一些特殊的情况,需要一些小技巧才能够处理.引用后面定义的类型由于python不是编译型语言,如果在前......