代码之家  ›  专栏  ›  技术社区  ›  jkone27

F#-在编译时从字符串生成简单的空类型

  •  3
  • jkone27  · 技术社区  · 6 年前

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

    混合这个

    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 ()
    

    这是我脚本中的代码。fsx文件,我想我可能犯了一些愚蠢的错误。

    #r @".\testType\SimpleStringProvider.dll"
    
    open SimpleStringProvider
    
    type x = SimpleStringProvider.SingleStringTypeProvider<"test">
    

    错误 在脚本中。fsx文件

    非泛型类型“SimpleStringProvider”。SingleStringTypeProvider' 不需要任何类型参数,但这里提供了1个类型 参数(个)

    1 回复  |  直到 4 年前
        1
  •  5
  •   Tomas Petricek    6 年前

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

    我还没有测试过这个,所以您可能需要做一些调整,但我认为它应该可以工作。