繁体   English   中英

F#ICastableTo <'T等效?

[英]F# ICastableTo<'T> equivalent?

您无法在F#中实现通用接口的多个实例。 在我的情况下,这是一个无赖,因为我计划实现一个名为ICastableTo <'T的接口,可用于模式匹配:

type ICastableTo<'T> =
    /// <summary>
    /// Returns a casted version of the object
    /// </summary>
    member this.Value : 'T

...
(*x:obj*)
match x with
| :? ICastableTo<SomeType> as x -> doSomethingWith(x.Value)
| _ -> invalidOp("can't cast like that")

但是,当我尝试实际使用它时,我遇到了一个问题,因为我无法实现ICastableTo接口的多个版本(请参阅在不同的通用实例中实现相同的接口 ),但我的一些类实际上可以转换为多个类型。

这里最好的选择是什么? 我当然可以定义一个ICastable接口,并使用一个“PossibleCasts”属性来公开所有可用的转换委托,但这并不是非常漂亮,并且在继承方面表现不佳。


这是我的代码的样子:

type BindableFunction<'T,'V>(func : 'T -> 'V) =
    member val Parent : 'T = nothing with get, set
    interface Specializable with
        member SpecializeFor(x: obj) =
            match x with | :? ICastable<'T> as x -> Parent <- x.Value | _ -> invalidOp("")

然后我有我的可投手课程。 例如,我有一个TCell类,它具有对Cell(组合)的引用,因此可以将其转换为Cell以进行函数绑定,即使这两种类型之间没有继承链接。

我认为我最终要做的是生成“匹配x与| ICastable <'T>”是非泛型的(也就是说,我将使用ICastableOf_Cell并使用Reflection找到好的界面(按名称获取类型)然后使用Reflection.Emit生成代码。

另一个选择是给BindableFunction两个泛型类型,一个是值类型,另一个是ICastableOf_Cell,这可能是一个更好的主意,但会使我的代码在各个地方更加冗长。

最后,我采用了以下方法:

type BindableFunction<'T,'V>(convert: obj -> 'T, func : 'T -> 'V) =
    member val Parent : 'T = nothing with get, set
    interface Specializable with
        member SpecializeFor(x: obj) =
            match x with 
            | :? 'T as x -> (Parent <- x) 
            | _          -> (Parent <- convert(x))

这允许我使用每种类型的唯一接口,因此不使用通用接口。

let CastToCell = ref(fun(o:obj) -> match o with | :? ICellScope as o -> o.ICell.Cell | _ -> invalidOp("invalid scope conversion"))

最后:

new BindableFunction<Cell,_>(!CastToCell,...)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM