29 people like it.
Like the snippet!
Convert a obj list to a typed list without generics
This is used for building things with reflection at runtime. As ConstructorInfo arguments require typed collections, it is necessary when parsing to reflected records to first build up contents and then afterward convert the collected obj[] to a 'a[]. This is finally cast back to obj so it can be used as a ConstructorInfo argument.
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:
|
type ReflectiveListBuilder =
static member BuildList<'a> (args: obj list) =
[ for a in args do yield a :?> 'a ]
static member BuildTypedList lType (args: obj list) =
typeof<ReflectiveListBuilder>
.GetMethod("BuildList")
.MakeGenericMethod([|lType|])
.Invoke(null, [|args|])
//Also, here's a caching version because reflection is slow. System.Type doesn't
//support the comparison constraint so I just use the the full name of the type.
type CachingReflectiveListBuilder =
static member ReturnTypedListBuilder<'a> () : obj list -> obj =
let createList (args : obj list) = [ for a in args do yield a :?> 'a ] :> obj
createList
static member private builderMap = ref Map.empty<string, obj list -> obj>
static member BuildTypedList (lType: System.Type) =
let currentMap = !CachingReflectiveListBuilder.builderMap
if Map.containsKey (lType.FullName) currentMap then
currentMap.[lType.FullName]
else
let builder = typeof<CachingReflectiveListBuilder>
.GetMethod("ReturnTypedListBuilder")
.MakeGenericMethod([|lType|])
.Invoke(null, null)
:?> obj list -> obj
CachingReflectiveListBuilder.builderMap := Map.add lType.FullName builder currentMap
builder
|
static member ReflectiveListBuilder.BuildList : args:obj list -> 'a list
Full name: Script.ReflectiveListBuilder.BuildList
val args : obj list
type obj = System.Object
Full name: Microsoft.FSharp.Core.obj
type 'T list = List<'T>
Full name: Microsoft.FSharp.Collections.list<_>
val a : obj
static member ReflectiveListBuilder.BuildTypedList : lType:System.Type -> args:obj list -> obj
Full name: Script.ReflectiveListBuilder.BuildTypedList
val lType : System.Type
val typeof<'T> : System.Type
Full name: Microsoft.FSharp.Core.Operators.typeof
type ReflectiveListBuilder =
static member BuildList : args:obj list -> 'a list
static member BuildTypedList : lType:Type -> args:obj list -> obj
Full name: Script.ReflectiveListBuilder
type CachingReflectiveListBuilder =
static member BuildTypedList : lType:Type -> (obj list -> obj)
static member ReturnTypedListBuilder : unit -> (obj list -> obj)
static member private builderMap : Map<string,(obj list -> obj)> ref
Full name: Script.CachingReflectiveListBuilder
static member CachingReflectiveListBuilder.ReturnTypedListBuilder : unit -> (obj list -> obj)
Full name: Script.CachingReflectiveListBuilder.ReturnTypedListBuilder
val createList : (obj list -> obj)
static member private CachingReflectiveListBuilder.builderMap : Map<string,(obj list -> obj)> ref
Full name: Script.CachingReflectiveListBuilder.builderMap
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<_>
Multiple items
module Map
from Microsoft.FSharp.Collections
--------------------
type Map<'Key,'Value (requires comparison)> =
interface IEnumerable
interface IComparable
interface IEnumerable<KeyValuePair<'Key,'Value>>
interface ICollection<KeyValuePair<'Key,'Value>>
interface IDictionary<'Key,'Value>
new : elements:seq<'Key * 'Value> -> Map<'Key,'Value>
member Add : key:'Key * value:'Value -> Map<'Key,'Value>
member ContainsKey : key:'Key -> bool
override Equals : obj -> bool
member Remove : key:'Key -> Map<'Key,'Value>
...
Full name: Microsoft.FSharp.Collections.Map<_,_>
--------------------
new : elements:seq<'Key * 'Value> -> Map<'Key,'Value>
val empty<'Key,'T (requires comparison)> : Map<'Key,'T> (requires comparison)
Full name: Microsoft.FSharp.Collections.Map.empty
Multiple items
val string : value:'T -> string
Full name: Microsoft.FSharp.Core.Operators.string
--------------------
type string = System.String
Full name: Microsoft.FSharp.Core.string
static member CachingReflectiveListBuilder.BuildTypedList : lType:System.Type -> (obj list -> obj)
Full name: Script.CachingReflectiveListBuilder.BuildTypedList
namespace System
type Type =
inherit MemberInfo
member Assembly : Assembly
member AssemblyQualifiedName : string
member Attributes : TypeAttributes
member BaseType : Type
member ContainsGenericParameters : bool
member DeclaringMethod : MethodBase
member DeclaringType : Type
member Equals : o:obj -> bool + 1 overload
member FindInterfaces : filter:TypeFilter * filterCriteria:obj -> Type[]
member FindMembers : memberType:MemberTypes * bindingAttr:BindingFlags * filter:MemberFilter * filterCriteria:obj -> MemberInfo[]
...
Full name: System.Type
val currentMap : Map<string,(obj list -> obj)>
property CachingReflectiveListBuilder.builderMap: Map<string,(obj list -> obj)> ref
val containsKey : key:'Key -> table:Map<'Key,'T> -> bool (requires comparison)
Full name: Microsoft.FSharp.Collections.Map.containsKey
property System.Type.FullName: string
val builder : (obj list -> obj)
val add : key:'Key -> value:'T -> table:Map<'Key,'T> -> Map<'Key,'T> (requires comparison)
Full name: Microsoft.FSharp.Collections.Map.add
More information