F#访问继承类型的字段

时间:2015-09-08 11:49:13

标签: inheritance f#

鉴于我有一个像这样定义的基类型:

[<AbstractClass>]
type HookBase(hookType: HookId, threadId: int) =
    let mutable hHook = IntPtr.Zero
    ...

    member this.SetHook() =
        // Set the hook using SetWindowsHookEx(...)
        ...
        hHook <- hhk

    member this.Unhook() =
        // Remove the hook
        hHook <- IntPtr.Zero

和这样的派生类型:

type ForegroundIdleHook(thread: uint32) as this =
    inherit HookBase(HookId.WH_FOREGROUNDIDLE, int thread)

    let hookCallback nCode wParam lParam =
        ...
        CallNextHookEx((* here has to be the hook's handle *), nCode, wParam, lParam)

    ...

因为我不希望每个代码都有SetHook()Unhook()代码 类型(最后将有15种钩子类型),我想到使用基本类型。但是F#不支持protected成员,我现在有问题要在派生类型中获取hHook并在基类型中设置回调。

我想过使用CallerMemberNameAttribute和预定义的方法来实现这个目标:

// Base type
member this.SetCallback(callback: HookProc, [<CallerMemberName>] ?name: string) =
    ...

member this.GetHHook([<CallerMemberName>] ?name: string) =
    ...

// Derived type
do
    this.SetCallback(this.Proc)

member private this.Proc = HookProc(hookCallback)

SetCallback的情况下,可以建立一个计数器以确保只有一个方法的调用,但是对GetHHook不起作用,因为可以设置和取消设置挂钩实例中有好几次&#39;寿命。

此外,由于其他被调用者也可以使用与所需方法相同的名称这种方式,这种方式并非愚蠢,我也不想拥有这些方法的公共范围。 除了我的测试之外,似乎该属性不适用于F#,因为必须为参数提供显式默认值。 (我在这里错过了什么吗?)

有没有更好的方法来获取钩子的句柄并设置回调而不是让基本类型具有15次所述方法?

修改:如上所述here,F#不支持CallerMemberName属性,因此使用它的选项不适用。

1 个答案:

答案 0 :(得分:0)

您在派生类型中需要什么句柄?仅适用于CallNextHookEx

然后根本不公开它,而是让SetCallback接受IntPtr -> HookProc类型的函数:

// Base type
member this.SetCallback(makeCallback: IntPtr -> HookProc) = 
   let callback = makeCallback hHook
   // do whatever you're supposed to do with the callback

// Derived type 
let hookCallback handle nCode wParam lParam =
    ...
    CallNextHookEx(handle, nCode, wParam, lParam)

do this.SetCallback(fun handle -> HookProc(hookCallback handle))

必须有更好的设计才能找到,而不仅仅是复制OOP模式,但我并不期待阅读有关Hooks API的信息。