Created
May 24, 2020 21:55
-
-
Save odytrice/313b2107f6ad52de12ae89f35941d4b2 to your computer and use it in GitHub Desktop.
Simple F# Type Provider for Mutable Records
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace TestProvider.Provided | |
open System.Reflection | |
open FSharp.Core.CompilerServices | |
open ProviderImplementation.ProvidedTypes | |
open System.Collections.Generic | |
open Microsoft.FSharp.Quotations | |
[<TypeProvider>] | |
type SampleProvider(config) as this = | |
inherit TypeProviderForNamespaces(config) | |
let ns = "SampleProvider.Provided" | |
let asm = Assembly.GetExecutingAssembly() | |
let addProperty (name: string) (_: 'T) (baseType: ProvidedTypeDefinition) = | |
let getter (args: Quotations.Expr list) = <@@ ((%%args.[0]:obj) :?> Dictionary<string,obj>).[name] :?> 'T @@> | |
let setter (args: Quotations.Expr list) = <@@ ((%%args.[0]:obj) :?> Dictionary<string,obj>).[name] <- (%%args.[1]:'T) @@> | |
let myInstanceProperty = | |
ProvidedProperty(name, | |
typeof<'T>, | |
isStatic = false, | |
getterCode = getter, | |
setterCode = setter) | |
baseType.AddMember myInstanceProperty | |
baseType | |
let addMethod (method: ProvidedMethod) (baseType: ProvidedTypeDefinition) = | |
baseType.AddMember method | |
baseType | |
let createType name (parameters: obj[]) = | |
let aString = parameters.[0] :?> string | |
let myType = ProvidedTypeDefinition(asm, ns, name, Some typeof<obj>, isErased = true) | |
let props = [ | |
"FirstName" | |
"LastName" | |
"Date" | |
] | |
let propExpr = Expr.NewArray(typeof<string>, props |> List.map (Expr.Value)) | |
let constructor = | |
<@@ | |
let items = %%propExpr:string[] | |
let d = Dictionary<string, obj>() | |
for item in items do | |
d.Add(item, null) | |
d | |
@@> | |
let ctor = ProvidedConstructor([], invokeCode = fun args -> constructor) | |
myType.AddMember(ctor) | |
let greetMethod (args: Expr list) = | |
<@@ | |
let state = (%%args.[0]:obj) :?> Dictionary<string,obj> | |
let firstName = state.["FirstName"]:?> string | |
let lastName = state.["LastName"] :?> string | |
let date = state.["Date"] :?> System.DateTime | |
sprintf "Hello my name is %s %s, The time is %O" firstName lastName date | |
@@> | |
let greet = ProvidedMethod("Greet",[],typeof<string>,isStatic = false, invokeCode = greetMethod) | |
myType | |
|> addProperty props.[0] Unchecked.defaultof<string> | |
|> addProperty props.[1] Unchecked.defaultof<string> | |
|> addProperty props.[2] Unchecked.defaultof<System.DateTime> | |
|> addMethod greet | |
let provider = | |
ProvidedTypeDefinition(asm,ns, "RecordProvider", Some typeof<obj>) | |
let parameters = | |
[ ProvidedStaticParameter("Name", typeof<string>) ] | |
do | |
provider.DefineStaticParameters(parameters, createType) | |
this.AddNamespace(ns, [ provider ]) | |
[<assembly: TypeProviderAssembly>] | |
do() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment