2

これは、タイプ セーフな方法でサードパーティの型を拡張するという以前の質問に関連しています。いくつかの良い答えがありましたが、それらはコンパイル時に認識されている具象型に依存しています。私はこれに依存することはできません。型が箱入りの場合もあります。サードパーティの型を拡張して動的ディスパッチをシミュレートする方法はありますか?

私は自分のライブラリにインターフェースを使用します。例えば:

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)

しかし、ランタイム キャストとインライン化を組み合わせることは明らかに不可能です。

4

1 に答える 1

3

System.Object私があなたの質問を正しく理解しているなら、あなたは未知のタイプ( )の動的にロードされたオブジェクトを取り、それをいくつかの構造タイプにキャストし、できればオブジェクトがによって指定されたすべての操作をサポートすることを保証するキャストのような操作をしたいと思いますこのタイプ。

そのための標準的な機械はないと思いますが、を使用して実装できますSystem.Reflection. Emit少し前に、C#とPHPの間の相互運用性のために同様の何かを実装しました。

アイデアは、インターフェイスを実装するクラスを動的に生成する関数を作成することであり、インターフェイスのすべてのメンバーは、ラップされたオブジェクトのメンバーに委任されるだけです。オブジェクトをラップしている間、すべてのメンバーが存在し、正しい署名を持っていることを確認できます(ただし、オブジェクトは実際には同じインターフェースを実装する必要はありません)。

これはコードサンプルには少し多すぎるコードですが、一般的なアイデアも役立つことを願っています(そこでどのように行われるかを確認したい場合は、 Phalangerソースコードでメソッドを検索してください)。NewObject

于 2012-04-05T16:43:52.270 に答える