我正在引用的配置文件是否需要位于项目的主目录中?

时间:2016-11-01 14:55:22

标签: f# config

我正在尝试将连接字符串和凭据数据存储在.config文件中。我无法使用连接/凭证将配置推送到repo;配置将位于一个安全的同步文件夹中,不是主目录。

我可以将连接/凭据存储在主目录的app.config文件中,并使用FSharp.Configuration库访问它:

type connection = AppSettings<"app.config">

但如果我尝试访问其他目录中的配置

open System.IO
open FSharp.Configuration

let baseDirectory = __SOURCE_DIRECTORY__
let baseDirectory' = Directory.GetParent(baseDirectory)
let configPath = "Tresor\app.config"
let fullConfigPath = Path.Combine(baseDirectory'.FullName, configPath)
type Settings = AppSettings<fullConfigPath>

出现fullConfigPath错误
This is not a valid constant expression or custom attribute value.

即使我尝试使用yaml类型提供程序

let yamlPath = "Tresor\Config.yaml"
let fullYamlPath = Path.Combine(baseDirectory'.FullName, yamlPath)
type Config = YamlConfig<FilePath = fullYamlPath>

我的fullYamlPath收到了类似的错误。

有没有理由我无法访问主目录之外的文件?我正确构建文件路径吗?

1 个答案:

答案 0 :(得分:5)

简短回答抱歉,您可能搞砸了,尽管使用{em>可能的SelectExecutableFile有一种解决方法为你工作。

答案很长:
这不是类型提供程序的工作方式。

当您使用类型提供程序为您提供类型时,类型的提供是在编译时发生的(否则,这将是什么意思?)。这意味着类型提供程序所需的所有输入需要在编译时知道。但是在您的代码中,fullConfigPathfullYamlPath的值在Path.Combine执行之前是不可知的,这只会在运行时发生。

假设的工作方式是,类型提供者需要一些&#34;模板&#34;文件(或数据库,或URL,或其他任何东西),它可以分析并从其内容生成类型。然后,稍后,在运行时,您将指定从哪里获取实际的数据

重申一下,这一切都分两个阶段进行:

  1. 数据形状(又名&#34;结构&#34;又名&#34;架构&#34;)在编译时。
  2. 运行时的实际数据。
  3. 这就是数据库提供商通常的工作方式:

    // Pseudocode. I don't have actual libraries handy.
    type Db = SqlProvider<"Server=localhost;Database=my_development_db;Integrated Security=true">
    
    let dbConnection = Db.OpenConnection Config.ProductionConnectionString
    

    理论上AppSettingsYamlConfig提供商的工作方式有些相似:

    type Config = AppSettings<"app.config">
    let config = Config.OpenConfigFile "MyProgram.exe.config"
    let someSetting = config.SomeSetting;
    

    不幸的是,情况并非如此(出于某种原因)。

    YamlConfig提供程序没有任何方法可以加载备用配置文件(它始终会查找在编译时指定的配置文件)。但是AppSettings提供商确实通过SelectExecutableFile方法为您提供了some control。这是一种静态方法,您可以调用该方法以便一劳永逸地选择数据源。它也没有采用配置文件路径,只有exe文件路径,然后passes to ConfigurationManager.OpenExeConfiguration

    type Config = AppSettings<"app.config">
    Config.SelectExecutableFile "MyProgram.exe"
    
    let someSetting = Config.SomeSetting;
    

    这使我不确定如何使用网络应用。

    我认为这可以提供解决方法:调用SelectExecutableFile并传递配置文件的路径,而不是.config扩展名,这应该可行。但是您还需要创建一个具有相同名称的虚拟文件,但没有.config扩展名(代表exe文件),因为库checks for its presence

    底线是,不支持您尝试做的事情,这很遗憾,我建议您file an issue