スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

F#入門初級編 第15回 Delegates と Events(3)

まずは前回使用したPublisherExampWithDelgクラス関連のコードを再掲します。

type WhatTimeDidItHappenEventArgs (dateTime : System.DateTime) =
    inherit System.EventArgs()
    member this.DateTime = dateTime

type DelegateForPublisherExampWithDelg =
                    delegate of obj * WhatTimeDidItHappenEventArgs -> unit

type PublisherExampWithDelg () =
    let _event1 =
        new Event< DelegateForPublisherExampWithDelg,WhatTimeDidItHappenEventArgs>()
    member this.SomethingHappen() =
        _event1.Trigger(this,new WhatTimeDidItHappenEventArgs( System.DateTime.Now ))
    member this.Event1 = _event1.Publish
   
ここでは、Event1プロパティが外部との窓口になって、ここに対して、t.Event1.AddHandler(delExpamp1)というようにdelegateを登録するのでした。

ひとつインスタンスを作ってみてthis.Event1の型をしらべてみます。

> let t = new PublisherExampWithDelg();;
val t : PublisherExampWithDelg

> t.Event1;;

val it :
  IEvent<DelegateForPublisherExampWithDelg,WhatTimeDidItHappenEventArgs> =
  <StartupCode$FSharp-Core>.$Event+get_Publish@68-1[FSI_0011+DelegateForPublisherExampWithDelg,FSI_0011+WhatTimeDidItHappenEventArgs]

ということでIEvent<'Del,'T>型であることがわかります。
F#のControl.Event ModuleにはIEvent型の値を引数にとる関数がいくつか収められているので今回はそれの紹介をしていきたいと思います。

○Filter

// Signature:
Event.filter : ('T -> bool) -> IEvent<'Del,'T> -> IEvent<'T> (requires delegate)

// Usage:
Event.filter predicate sourceEvent

predicate
Type: 'T -> bool

The function to determine which triggers from the event to propagate.

sourceEvent
Type: IEvent<'Del,'T>

The input event.

'Tは付加情報の型です。よって付加情報を受け取りbool値を返す関数と、IEvent<'Del,'T>型の値を引数にとって、新しいIEvent<'T>型の値を返します。
一体何がてきるかというと、制限をかけた新しい窓口を作ることができるのです。

留意点としてはオリジナルの窓口はIEvent<'Del,'T>型でしたが、新しい窓口はIEvent<T'>型となり型が変わっていることです。
IEvent<T'>型というのはIEvent<Handler<T'>,'Args>の略記です。
つまりトリガーが引かれた時実行されるものとしてはHandler<T'>型のインスタンスを渡すこととなります。
Handler型は
type Handler<'T> =
 class
  abstract this.Invoke : obj * 'T -> unit
 end
と定義されていて、例えば

let myHandler =
    new Handler<WhatTimeDidItHappenEventArgs>(
           fun sender args -> printfn "at %A event fired" args.DateTime
     )  //newは省略可

というようにインスタンス化できます。

それでは使ってみます。
例えば次のようにfilteredEvent1を定義します。

let filteredEvent1 =
    t.Event1
     |> Event.filter(fun (whatTimeArgs : WhatTimeDidItHappenEventArgs) ->
                        whatTimeArgs.DateTime.TimeOfDay.Seconds < 10)
                        //Event.filterのEventはモジュール名

こうすることで、eventが発火した時刻の秒が10未満の時だけ、このfilteredEvent1に登録された、handlerが実行される窓口ができました。(Eventモジュールのfiler関数を利用しました。)

上でやったようにhandlerは次のように作成できます。

let myHandler =
    new Handler<WhatTimeDidItHappenEventArgs>(
           fun sender args -> printfn "at %A event fired" args.DateTime
     )

さっき作ったfilteredEvent1窓口に登録します。
filteredEvent1.AddHandler (myHandler)

eventを手動で発火してみます。
> t.SomethingHappen();;
val it : unit = ()
> t.SomethingHappen();;
at 2009/09/01 20:58:01 event fired
val it : unit = ()
> t.SomethingHappen();;
at 2009/09/01 20:58:03 event fired
val it : unit = ()
> t.SomethingHappen();;
at 2009/09/01 20:58:06 event fired
val it : unit = ()
> t.SomethingHappen();;
at 2009/09/01 20:58:08 event fired
val it : unit = ()
> t.SomethingHappen();;
val it : unit = ()

秒が10未満のときだけ、登録したdelegateが実行されました。

なお次のように関数化して利用することもできます。

let filteredEvent1 sec =
    t.Event1
     |> Event.filter(fun (whatTimeArgs : WhatTimeDidItHappenEventArgs) ->
                        whatTimeArgs.DateTime.TimeOfDay.Seconds < sec) //< は不等号
    
let secondDependHandler =
    new Handler<WhatTimeDidItHappenEventArgs>(
           fun sender args -> printfn "at %A event fired" args.DateTime
     )
    
(filteredEvent1 30).AddHandler (secondDependHandler)

このように変えると、秒が30未満のときだけ、登録したdelegateが実行されます。

(注意)
IEvent<_,_>型のインスタンスにAddHandlerで加えるhandlerはdelgate型の値で
IEvent<>型のインスタンスにAddHandlerで加えるhandlerはHandler型の値であることに留意してください。

スポンサーサイト

テーマ : プログラミング
ジャンル : コンピュータ

コメントの投稿

非公開コメント

プロフィール

T GYOUTEN

Author:T GYOUTEN
F#と英単語とフリーソフトと読書に興味があります。
ホームページでフリーソフトも公開しています。どぞ御贔屓に。

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
フリーエリア
フリーエリア
blogram投票ボタン
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QRコード
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。