5 people like it.
Like the snippet!
Dynamic Invocation of Generic Functions In A Module
A quick snippet showing three different ways of dynamically/reflectively locating a module then invoking a generic function. The first two don't rely on a class. But the third is more readable/understandable for most .NET devs.
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:
|
open Microsoft.FSharp.Quotations.Patterns
module Test =
// https://stackoverflow.com/a/26621814
// relies on at least surface-level knowledge of how F# quotations work
let rec private moduleType = <@ moduleType @> |> function PropertyGet (_, info, _) -> info.DeclaringType
let ModuleTypeQt = moduleType
// https://stackoverflow.com/a/14706890
// relies on the fact that Modules are actually implemented as static classes
type private IAssemblyLocator = interface end
let ModuleTypeTo = typeof<IAssemblyLocator>.DeclaringType
let sayHi<'a> () =
printfn "Hello %A" (typeof<'a>.Name)
// not a module, but is perhaps the most understandable to most devs coming in
[<AbstractClass; Sealed>]
type Test private () =
static member sayHi<'a> () =
printfn "Hello %A" (typeof<'a>.Name)
Test.ModuleTypeQt.GetMethod(nameof Test.sayHi).MakeGenericMethod(typeof<unit>).Invoke(null, [| |])
Test.ModuleTypeTo.GetMethod(nameof Test.sayHi).MakeGenericMethod(typeof<unit>).Invoke(null, [| |])
typeof<Test>.GetMethod(nameof Test.sayHi).MakeGenericMethod(typeof<unit>).Invoke(null, [| |])
|
namespace Microsoft
namespace Microsoft.FSharp
namespace Microsoft.FSharp.Quotations
module Patterns
from Microsoft.FSharp.Quotations
val private moduleType : System.Type
active recognizer PropertyGet: Quotations.Expr -> (Quotations.Expr option * System.Reflection.PropertyInfo * Quotations.Expr list) option
val info : System.Reflection.PropertyInfo
property System.Reflection.MemberInfo.DeclaringType: System.Type with get
val ModuleTypeQt : System.Type
type private IAssemblyLocator
val ModuleTypeTo : System.Type
val typeof<'T> : System.Type
val sayHi<'a> : unit -> unit
val printfn : format:Printf.TextWriterFormat<'T> -> 'T
Multiple items
type AbstractClassAttribute =
inherit Attribute
new : unit -> AbstractClassAttribute
--------------------
new : unit -> AbstractClassAttribute
Multiple items
type SealedAttribute =
inherit Attribute
new : unit -> SealedAttribute
new : value:bool -> SealedAttribute
member Value : bool
--------------------
new : unit -> SealedAttribute
new : value:bool -> SealedAttribute
Multiple items
module Test
from Script
--------------------
type Test =
private new : unit -> Test
static member sayHi : unit -> unit
--------------------
private new : unit -> Test
val nameof : 'T -> string
Multiple items
val sayHi<'a> : unit -> unit
--------------------
static member Test.sayHi : unit -> unit
type unit = Unit
More information