他人様のブログを和訳・"A Simple AppSettings Type Provider"
味を占めたんだ!!!!
他人様のブログを和訳したら、なかなか面白かったので今日もやります!!!!
味を占めたんだ!!!!
今日もDaniel Mohl さんのブログから、2011年9月29日のエントリです
2011/09/29 シンプルな AppSetting Type Provider F# 3.0 Developer Preview が公開され、私は自由時間の多くをType Providerで遊んで過ごしています。 Type Providerを使うための導入ガイドとサンプルの発表もあって、 (食事は言うまでもなく)寝るための時間を確保するのも苦労しています。 かなりの量の実験をした後、私は最初のType Providerを書いてみました。 本当に単純でプロダクト品質と呼べるものではありませんが、とても楽しいエクササイズとなりました。 基本的なアイデアはconfigファイルからappSetting要素を読み出し、値を適切にパースし、型安全な方法でそれらと対応させることです。 configファイルのサンプルは以下のような感じです:
<?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>
Type Provider のコードは以下の通りです:
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()
最後にどのように使うかのサンプルを示します:
#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
感想
F#3.0Betaが発表(Introducing Visual F# 3.0 Beta! | Visual Studio F# Team Blog)された今、少し古いかなと思いましたが、
Type Provider をどのように使えば良いのか全然分からなかったので翻訳しました。
やっぱり難しいですねType Provider...
便利なのか否かの判断はまだ保留中です。