dependency-injection - F# Host.CreateDefaultBuilder().ConfigureServices() 没有 HostBuilderContext
问题描述
我正在创建一个 WorkerService。
我有信心用 C# 做这件事,但我在 F# 版本上苦苦挣扎。
C# 程序.cs
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
// here I have access to the builded configuration
// read stuff from configuration
var interval = TimeSpan.Parse(hostContext.Configuration["Service:Run:interval"]);
services.AddHostedService<Worker>();
});
F# 程序.fs
let CreateHostBuilder (args) =
Host.CreateDefaultBuilder()
.ConfigureServices(
fun (services:IServiceCollection) -> //hostContext:HostBuilderContext,
//fun (context:HostBuilderContext, services:IServiceCollection) ->
// where is the builded configuration ???
//let configuration = ???
services.AddHostedService<Worker>() |> ignore
)
我不知道如何阅读配置来设置我需要注入的一些服务设置。
为什么 IHostBuilder.ConfigureServices 的签名不同?
C#
IHostBuilder ConfigureServices(Action configureDelegate);
F#
IHostBuilder 配置服务:configureDelegateAction -> IHostBuilder
HostBuilderContext被传递给.ConfigureContainer ()所以我尝试了这个:
open System
open System.Threading
open System.Threading.Tasks
type IMyWorker =
abstract member Start: unit -> unit
type MyWorker(interval:TimeSpan) =
inherit BackgroundService()
override this.ExecuteAsync (step:CancellationToken):Task = Task.CompletedTask
interface IMyWorker with
member this.Start() = ()
let CreateHostBuilder (args) =
// 1. this is empty
//let configuration = ConfigurationBuilder().Build()
//let interval = TimeSpan.Parse(configuration.["Service:Run:interval"])
let mutable loadedConfiguration:Option<IConfiguration> = None
Host.CreateDefaultBuilder()
.ConfigureHostConfiguration( fun(confBuilder:IConfigurationBuilder) ->
// it's ok here to read more settings, like "serilog.json" for example ?
// 2. this is still empty
//let configuration = confBuilder.Build()
//let interval = TimeSpan.Parse(configuration.["Service:Run:interval"])
// where to store the values ? configuration.[""]
()
)
.ConfigureContainer( fun (hostContext:HostBuilderContext) ->
// 5. this is ok, it is builded properly
// but ist is called after ConfigureServices()
loadedConfiguration <- Some(hostContext.Configuration) // :> IConfigurationRoot
let interval = TimeSpan.Parse(hostContext.Configuration.["Service:Run:interval"])
()
)
.ConfigureServices(
fun(services:IServiceCollection) ->
// 4. this is empty
//let configuration = ConfigurationBuilder().Build()
//let interval = TimeSpan.Parse(configuration.["Service:Run:interval"])
if loadedConfiguration.IsNone then failwith "configuration not loqaded yet"
let interval = TimeSpan.Parse(loadedConfiguration.Value.["Service:Run:interval"])
//let interval = TimeSpan.Parse("00:01:00")
let worker = new MyWorker(interval)
services.AddSingleton<IMyWorker>(worker) |> ignore
)
但它不起作用,因为ConfigureContainer()在ConfigureServices()之后调用,我认为应该有一种方法可以使用构建的配置而不将其存储在某处。
它应该如何工作?
解决方案
这应该可以解决问题:
let createHostBuilder args =
Host
.CreateDefaultBuilder(args)
.ConfigureServices (fun hostContext services ->
let interval = TimeSpan.Parse(hostContext.Configuration.["Service:Run:interval"]);
services.AddHostedService<Worker>() |> ignore
)
推荐阅读
- javascript - 在图像缩略图中阅读更多信息
- go - 创建通用函数以从地图中提取值
- docker - 如何使用 docker(不是 vagrant 或 virtualbox)在 mac os High Sierra 上运行 kubernetes?
- python - 当值为“无”时如何使用理解来查找字典键?
- json - Spark数据框需要json文件作为一行中的一个对象?
- algorithm - 如何通过使用一些索引来制作高效的归并排序算法
- javascript - 通过对象的值对对象中的值进行排序 - js
- c# - 循环依赖 C# 项目与 Python 包
- spring-boot - Spring boot as a service 不获取活动配置文件设置
- scala - Spark dataFrame 没有 createGlobalTempView() 函数?