【问题标题】:F# - Generate simple empty type from string at compile timeF# - 在编译时从字符串生成简单的空类型
【发布时间】:2018-10-20 20:34:33
【问题描述】:

我想知道是否可以从字符串生成类似于简单类型提供程序(记录或联合,没有成员,只是与字符串名称匹配的名称)的东西, 在编译时。

混合这个

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 文件中

非泛型类型“SimpleStringProvider.SingleStringTypeProvider” 不期望任何类型参数,但这里给出了 1 种类型 论点

【问题讨论】:

  • 作为旁注,我不能“继承 TypeProviderForNamespaces()”,但只有一个参数“继承 TypeProviderForNamespaces(config)”的重载......这可能是一个问题吗?我正在使用来自 github 中的 sdk 的 providedTypes.fs 和 providedTypes.fsi

标签: string reflection f# compile-time static-typing


【解决方案1】:

您可以提供嵌套类型,这些类型可以基于静态参数。在您的示例中,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()

我尚未对此进行测试,因此您可能需要进行一些调整,但我认为它应该可以工作。

【讨论】:

  • 我正在为此苦苦挣扎,但我仍然无法从我的脚本文件中正确调用它。也许我错过了什么?
  • @jkone27 你能发布你当前版本的错误细节吗? (最好作为一个新问题,因为这样更多人会看到它..)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-18
  • 2012-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-16
相关资源
最近更新 更多