第三方类型的动态调度

时间:2012-04-05 14:52:30

标签: f# dynamic-dispatch

这与我previous question关于以类型安全方式扩展第三方类型有关。有一些很好的答案,但它们依赖于编译时已知的具体类型。我不能依赖于此。有时类型是盒装的。有没有办法扩展第三方类型来模拟动态调度?

我会为自己的库使用接口。例如:

type ICanSerialize =
  abstract ToSerializable : unit -> IDictionary<string,obj>

type B(items: obj[]) =
  interface ICanSerialize with
    member __.ToSerializable() = 
      dict ["Items", items |> Array.map (fun x -> 
        (x :?> ICanSerialize).ToSerializable()) |> box]

作为旁注,如果我们可以这样做会很好:

let inline toSerializable x =
  (^T : (member ToSerializable : unit -> IDictionary<string,obj>) x)

let x = obj()
let d = toSerializable (unbox x)

但显然不可能将运行时强制转换和内联组合起来。

1 个答案:

答案 0 :(得分:3)

如果我正确地理解了你的问题,你想要进行一些类似于强制转换的未知类型对象(System.Object)的强制转换操作,并将其转换为某种结构类型,并且最好保证object支持此类型指定的所有操作。

我认为没有标准机制,但可以使用System.Reflection. Emit来实施。我为interoperability between C# and PHP some time ago实现了类似的功能。

我们的想法是编写一个动态生成实现接口的类的函数,并将接口的所有成员简单地委托给包装对象的成员。在包装对象时,您可以检查所有成员是否存在并具有正确的签名(但该对象实际上不必实现相同的接口)。

这对于代码示例来说有点太多代码,但我希望一般的想法也很有用(如果你想看看它是如何完成的话,请搜索Phalanger source code NewObject方法)