F# - 在编译时从字符串生成简单的空类型
F# - Generate simple empty type from string at compile time
我想知道是否有可能从字符串生成类似于简单类型提供程序(Record 或 Union,没有成员,只有与字符串名称匹配的名称)的东西,
在编译时。
混合这个
http://www.readcopyupdate.com/blog/2014/09/18/faking-typeclasses-using-static-type-constraints.html
还有这个
Create Discriminated Union Case from String
或类似的记录类型方法。
我想获得什么,例如(不一定使用相同的方法):
[<Literal>]
let myTypeName = "One"
type SingleStringTypeProvider = ... (here implementation)
type Provided = SingleStringTypeProvider<singleString>
let typeName = typeof<Provided.One>.Name
最终结果:
一个是编译时的类型(不是方法也不是函数)
编辑
正如第一个答案中所建议的那样(非常感谢 :)),我尝试使用提供的类型来实现它,但是当我试图从我的脚本文件访问类型提供者时我仍然在努力,显然我只看到创建的类型但不是类型提供者本身?
module SimpleStringProvider
open ProviderImplementation.ProvidedTypes
open Microsoft.FSharp.Core.CompilerServices
[<TypeProvider>]
type SingleStringTypeProvider (config : TypeProviderConfig) as this =
inherit TypeProviderForNamespaces (config)
let asm = System.Reflection.Assembly.GetExecutingAssembly()
let ns = "SimpleStringProvider"
let stringProvider = ProvidedTypeDefinition(asm, ns, "SingleStringTypeProvider", Some(typeof<obj>))
// Define one static parameter with type name
let parameter = ProvidedStaticParameter("TypeName", typeof<string>)
do stringProvider.DefineStaticParameters([parameter], fun typeName args ->
// Create the main type (this corresponds to `Provided`)
let resTy = ProvidedTypeDefinition(asm, ns, typeName, Some(typeof<obj>))
// Add a nested type as a member using the name from the parameter
let typeName = args.[0] :?> string
ProvidedTypeDefinition(typeName, None)
|> resTy.AddMember
resTy )
[<assembly:TypeProviderAssembly>]
do ()
这是我的 script.fsx 文件中的代码,我想我可能犯了一些愚蠢的错误。
#r @".\testType\SimpleStringProvider.dll"
open SimpleStringProvider
type x = SimpleStringProvider.SingleStringTypeProvider<"test">
错误 script.fsx 文件
The non-generic type 'SimpleStringProvider.SingleStringTypeProvider'
does not expect any type arguments, but here is given 1 type
argument(s)
您可以提供嵌套类型,这些类型可以基于静态参数。在您的示例中, Provided
是一种类型, Provided.One
可以是嵌套类型。
为此,您可以这样写:
[<TypeProvider>]
type public SingleStringTypeProvider(cfg:TypeProviderConfig) as this =
inherit TypeProviderForNamespaces()
// Generate namespace and the main type provider
let asm = System.Reflection.Assembly.GetExecutingAssembly()
let ns = "Samples"
let stringProvider = ProvidedTypeDefinition(asm, ns, "SingleStringTypeProvider", Some(typeof<obj>))
// Define one static parameter with type name
let parameter = ProvidedStaticParameter("TypeName", typeof<string>)
do stringProvider.DefineStaticParameters([parameter], fun typeName args ->
// Create the main type (this corresponds to `Provided`)
let resTy = ProvidedTypeDefinition(asm, ns, typeName, Some typeof<IniFile>)
// Add a nested type as a member using the name from the parameter
let typeName = args.[0] :?> string
ProvidedTypeDefinition(typeName, None)
|> resTy.AddMember
resTy )
[<assembly:TypeProviderAssembly>]
do()
我还没有测试过这个,所以你可能需要做一些调整,但我认为它应该可以工作。
我想知道是否有可能从字符串生成类似于简单类型提供程序(Record 或 Union,没有成员,只有与字符串名称匹配的名称)的东西, 在编译时。
混合这个
http://www.readcopyupdate.com/blog/2014/09/18/faking-typeclasses-using-static-type-constraints.html
还有这个
Create Discriminated Union Case from String
或类似的记录类型方法。
我想获得什么,例如(不一定使用相同的方法):
[<Literal>]
let myTypeName = "One"
type SingleStringTypeProvider = ... (here implementation)
type Provided = SingleStringTypeProvider<singleString>
let typeName = typeof<Provided.One>.Name
最终结果: 一个是编译时的类型(不是方法也不是函数)
编辑
正如第一个答案中所建议的那样(非常感谢 :)),我尝试使用提供的类型来实现它,但是当我试图从我的脚本文件访问类型提供者时我仍然在努力,显然我只看到创建的类型但不是类型提供者本身?
module SimpleStringProvider
open ProviderImplementation.ProvidedTypes
open Microsoft.FSharp.Core.CompilerServices
[<TypeProvider>]
type SingleStringTypeProvider (config : TypeProviderConfig) as this =
inherit TypeProviderForNamespaces (config)
let asm = System.Reflection.Assembly.GetExecutingAssembly()
let ns = "SimpleStringProvider"
let stringProvider = ProvidedTypeDefinition(asm, ns, "SingleStringTypeProvider", Some(typeof<obj>))
// Define one static parameter with type name
let parameter = ProvidedStaticParameter("TypeName", typeof<string>)
do stringProvider.DefineStaticParameters([parameter], fun typeName args ->
// Create the main type (this corresponds to `Provided`)
let resTy = ProvidedTypeDefinition(asm, ns, typeName, Some(typeof<obj>))
// Add a nested type as a member using the name from the parameter
let typeName = args.[0] :?> string
ProvidedTypeDefinition(typeName, None)
|> resTy.AddMember
resTy )
[<assembly:TypeProviderAssembly>]
do ()
这是我的 script.fsx 文件中的代码,我想我可能犯了一些愚蠢的错误。
#r @".\testType\SimpleStringProvider.dll"
open SimpleStringProvider
type x = SimpleStringProvider.SingleStringTypeProvider<"test">
错误 script.fsx 文件
The non-generic type 'SimpleStringProvider.SingleStringTypeProvider' does not expect any type arguments, but here is given 1 type argument(s)
您可以提供嵌套类型,这些类型可以基于静态参数。在您的示例中, Provided
是一种类型, Provided.One
可以是嵌套类型。
为此,您可以这样写:
[<TypeProvider>]
type public SingleStringTypeProvider(cfg:TypeProviderConfig) as this =
inherit TypeProviderForNamespaces()
// Generate namespace and the main type provider
let asm = System.Reflection.Assembly.GetExecutingAssembly()
let ns = "Samples"
let stringProvider = ProvidedTypeDefinition(asm, ns, "SingleStringTypeProvider", Some(typeof<obj>))
// Define one static parameter with type name
let parameter = ProvidedStaticParameter("TypeName", typeof<string>)
do stringProvider.DefineStaticParameters([parameter], fun typeName args ->
// Create the main type (this corresponds to `Provided`)
let resTy = ProvidedTypeDefinition(asm, ns, typeName, Some typeof<IniFile>)
// Add a nested type as a member using the name from the parameter
let typeName = args.[0] :?> string
ProvidedTypeDefinition(typeName, None)
|> resTy.AddMember
resTy )
[<assembly:TypeProviderAssembly>]
do()
我还没有测试过这个,所以你可能需要做一些调整,但我认为它应该可以工作。