Skip to content

Instantly share code, notes, and snippets.

@dmohl
Created September 29, 2011 16:41
Show Gist options
  • Save dmohl/1251208 to your computer and use it in GitHub Desktop.
Save dmohl/1251208 to your computer and use it in GitHub Desktop.
Example of a simple TypeProvider for reading AppSettings
namespace AppSettingsTypeProvider
open System
open System.IO
open System.Reflection
open Samples.FSharpPreviewRelease2011.ProvidedTypes
open Microsoft.FSharp.Core.CompilerServices
open System.Configuration
[<TypeProvider>]
type public AppSettingsProvider(config:TypeProviderConfig) as this =
inherit TypeProviderForNamespaces()
let namespaceName = "AppSettingsTypeProvider"
let currentAssembly = Assembly.GetExecutingAssembly()
let tySettings = ProvidedTypeDefinition(currentAssembly, namespaceName, "AppSettings", Some typeof<obj>)
let addSettings (configFileName:string) (tyDef:ProvidedTypeDefinition) =
tyDef.AddXmlDocDelayed(fun () -> sprintf "Provides a strongly typed representation of the appSettings in a provided config file.")
let filePath = Path.Combine(config.ResolutionFolder, configFileName)
let fileMap = ExeConfigurationFileMap(ExeConfigFilename=filePath)
let appSettings = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None).AppSettings.Settings
let tryParseWith func = func >> function
| true, value -> Some value
| false, _ -> None
let (|Bool|_|) = tryParseWith Boolean.TryParse
let (|Int|_|) = tryParseWith Int32.TryParse
let (|Double|_|) = tryParseWith Double.TryParse
do Seq.iter (fun (key) ->
let keyElement = match (appSettings.Item key).Value with
| Int fieldValue -> ProvidedLiteralField(key, typeof<int>, fieldValue)
| Bool fieldValue -> ProvidedLiteralField(key, typeof<bool>, fieldValue)
| Double fieldValue -> ProvidedLiteralField(key, typeof<Double>, fieldValue)
| fieldValue -> ProvidedLiteralField(key, typeof<string>, fieldValue.ToString())
do keyElement.AddXmlDocDelayed(fun () -> sprintf "Returns the value from the appSetting with key %s" key)
do tyDef.AddMember keyElement ) appSettings.AllKeys
let staticParams = [ProvidedStaticParameter("configFilePath", typeof<string>)]
do tySettings.DefineStaticParameters(staticParams,
fun typeName args ->
match args with
| [| :? string as configFileName |] ->
let ty = ProvidedTypeDefinition(assembly = currentAssembly,
namespaceName = namespaceName, typeName = typeName,
baseType = Some typeof<obj>, HideObjectMethods = true)
addSettings configFileName ty
ty
| _ -> failwith "unexpected parameter values")
do this.AddNamespace(namespaceName, [tySettings])
[<assembly:TypeProviderAssembly>]
do()
@dmohl
Copy link
Author

dmohl commented Sep 30, 2011

// Example of this TypeProvider in use

r "System"

r @"bin\debug\AppSettingsTypeProvider.dll"

open System
open AppSettingsTypeProvider

type settings = AppSettings<"App.config">
printfn "Test2 String: %s" settings.test2
printfn "Test Int: %i" settings.TestInt
printfn "Test Bool: %b" settings.TestBool
printfn "Test Double: %f" settings.TestDouble

@dmohl
Copy link
Author

dmohl commented Sep 30, 2011

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="test2" value="Some Test Value 5"/>
<add key="TestInt" value="102"/>
<add key="TestBool" value="True"/>
<add key="TestDouble" value="10.01"/>
</appSettings>
</configuration>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment