3 people like it.
Like the snippet!
Walking object graphs
Implemetation picked up from http://msdn.microsoft.com/en-us/library/system.runtime.serialization.objectmanager.aspx
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
|
open System
open System.Reflection
open System.Runtime.Serialization
let gatherObjs (o : obj) =
let gen = new ObjectIDGenerator()
let rec traverse (gathered : obj list) : obj list -> obj list =
function
| [] -> gathered
| o :: rest when o = null -> traverse gathered rest
| o :: rest ->
let firstTime = ref false
gen.GetId(o, firstTime) |> ignore
if firstTime.Value then
let t = o.GetType()
let nested =
if t.IsValueType then []
elif t.IsArray then
[ for e in (o :?> Array) -> e ]
else
let fields = t.GetFields(BindingFlags.Instance ||| BindingFlags.Public ||| BindingFlags.NonPublic)
[ for fInfo in fields -> fInfo.GetValue o ]
traverse (o :: gathered) (nested @ rest)
else traverse gathered rest
traverse [] [o]
let gatherTypes : obj -> _ =
gatherObjs
>> Seq.map (fun o -> o.GetType())
>> Seq.distinctBy (fun t -> t.AssemblyQualifiedName)
>> Seq.toList
|
namespace System
namespace System.Reflection
namespace System.Runtime
namespace System.Runtime.Serialization
val gatherObjs : o:obj -> obj list
Full name: Script.gatherObjs
val o : obj
type obj = Object
Full name: Microsoft.FSharp.Core.obj
val gen : ObjectIDGenerator
Multiple items
type ObjectIDGenerator =
new : unit -> ObjectIDGenerator
member GetId : obj:obj * firstTime:bool -> int64
member HasId : obj:obj * firstTime:bool -> int64
Full name: System.Runtime.Serialization.ObjectIDGenerator
--------------------
ObjectIDGenerator() : unit
val traverse : (obj list -> obj list -> obj list)
val gathered : obj list
type 'T list = List<'T>
Full name: Microsoft.FSharp.Collections.list<_>
val rest : obj list
val firstTime : bool ref
Multiple items
val ref : value:'T -> 'T ref
Full name: Microsoft.FSharp.Core.Operators.ref
--------------------
type 'T ref = Ref<'T>
Full name: Microsoft.FSharp.Core.ref<_>
ObjectIDGenerator.GetId(obj: obj, firstTime: byref<bool>) : int64
val ignore : value:'T -> unit
Full name: Microsoft.FSharp.Core.Operators.ignore
property Ref.Value: bool
val t : Type
Object.GetType() : Type
val nested : obj list
property Type.IsValueType: bool
property Type.IsArray: bool
val e : obj
type Array =
member Clone : unit -> obj
member CopyTo : array:Array * index:int -> unit + 1 overload
member GetEnumerator : unit -> IEnumerator
member GetLength : dimension:int -> int
member GetLongLength : dimension:int -> int64
member GetLowerBound : dimension:int -> int
member GetUpperBound : dimension:int -> int
member GetValue : [<ParamArray>] indices:int[] -> obj + 7 overloads
member Initialize : unit -> unit
member IsFixedSize : bool
...
Full name: System.Array
val fields : FieldInfo []
Type.GetFields() : FieldInfo []
Type.GetFields(bindingAttr: BindingFlags) : FieldInfo []
type BindingFlags =
| Default = 0
| IgnoreCase = 1
| DeclaredOnly = 2
| Instance = 4
| Static = 8
| Public = 16
| NonPublic = 32
| FlattenHierarchy = 64
| InvokeMethod = 256
| CreateInstance = 512
...
Full name: System.Reflection.BindingFlags
field BindingFlags.Instance = 4
field BindingFlags.Public = 16
field BindingFlags.NonPublic = 32
val fInfo : FieldInfo
FieldInfo.GetValue(obj: obj) : obj
val gatherTypes : (obj -> Type list)
Full name: Script.gatherTypes
module Seq
from Microsoft.FSharp.Collections
val map : mapping:('T -> 'U) -> source:seq<'T> -> seq<'U>
Full name: Microsoft.FSharp.Collections.Seq.map
val distinctBy : projection:('T -> 'Key) -> source:seq<'T> -> seq<'T> (requires equality)
Full name: Microsoft.FSharp.Collections.Seq.distinctBy
property Type.AssemblyQualifiedName: string
val toList : source:seq<'T> -> 'T list
Full name: Microsoft.FSharp.Collections.Seq.toList
More information