知道为什么在 F# 中跳过 C# 扩展调用吗?
Any idea why that C# extension call is skipped in F#?
由于某些原因该行
在我调试 F# Giraffe 应用程序时跳过 let configureServices (services : IServiceCollection)
中的 services.AddSingleton<IHostedService, CommandConsumer> |> ignore
。
有点令人沮丧的是程序编译,所以我希望程序能够在该行的断点处停止,但它没有。
奇怪的是,如果我使用扩展方法的完整命名空间,那么断点就可以工作...
Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton<IHostedService, CommandConsumer>(services) |> ignore
Program.fs
中的源代码:
module Rm.Accounting.Workflows.Api.App
open System
open System.Threading
open System.Threading.Tasks
open System.IO
open Microsoft.AspNetCore.Builder
open Microsoft.AspNetCore.Hosting
open Microsoft.Extensions.Logging
open Microsoft.Extensions.DependencyInjection
open Giraffe
open Microsoft.AspNetCore.Http
open Microsoft.Extensions.Hosting
type CommandConsumer()=
inherit BackgroundService()
override __.ExecuteAsync(cancellationToken : CancellationToken) =
Task.CompletedTask
let webApp = choose [
GET >=>
choose [
route "/" >=> redirectTo false "/health"
]
setStatusCode 404 >=> text "Not Found" ]
let errorHandler (ex : Exception) (logger : ILogger) =
logger.LogError(ex, "An unhandled exception has occurred while executing the request.")
clearResponse >=> setStatusCode 500 >=> text ex.Message
let configureApp (app : IApplicationBuilder) =
app.UseHealthChecks(PathString("/health")) |> ignore
let env = app.ApplicationServices.GetService<IHostingEnvironment>()
(match env.IsDevelopment() with
| true -> app.UseDeveloperExceptionPage()
| false -> app.UseGiraffeErrorHandler errorHandler)
.UseHttpsRedirection()
.UseStaticFiles()
.UseGiraffe(webApp)
let configureServices (services : IServiceCollection) =
// That line below stops the debugger if there a breakpoint.
// Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton<IHostedService, CommandConsumer>(services)
// |> ignore
// The line does not stop the debugger with a breakpoint while the one above can, weird.
services.AddSingleton<IHostedService, CommandConsumer> |> ignore
services.AddHealthChecks() |> ignore
services.AddGiraffe() |> ignore
let configureLogging (builder : ILoggingBuilder) =
builder.AddFilter(fun l -> l.Equals LogLevel.Error)
.AddConsole()
.AddDebug() |> ignore
[<EntryPoint>]
let main _ =
let contentRoot = Directory.GetCurrentDirectory()
let webRoot = Path.Combine(contentRoot, "WebRoot")
WebHostBuilder()
.UseKestrel()
.UseContentRoot(contentRoot)
.UseIISIntegration()
.UseWebRoot(webRoot)
.Configure(Action<IApplicationBuilder> configureApp)
.ConfigureServices(configureServices)
.ConfigureLogging(configureLogging)
.Build()
.Run()
0
第services.AddSingleton<IHostedService, CommandConsumer> |> ignore
行是语法错误,你把涉及的类型分解一下就知道了。
services.AddSingleton<IHostedService, CommandConsumer>
是 Func<unit, IServiceCollection>
,意味着它是一个尚未被调用的函数。
ignore
然后接收该函数但不对其进行任何操作。
为了将单例注册到服务,您实际需要的语法是 services.AddSingleton<IHostedService, CommandConsumer>() |> invoke
,意思是“执行 AddSingleton 调用并忽略 return 值。
您可以使用 services.AddHostedService(CommandConsumer) |> ignore
而不是 services.AddSingleton<IHostedService, CommandConsumer>() |> ignore
,并且 CommandConsumer
将存在于托管后台服务的单例中。有关该主题的讨论,请参阅 。
由于某些原因该行
在我调试 F# Giraffe 应用程序时跳过 let configureServices (services : IServiceCollection)
中的 services.AddSingleton<IHostedService, CommandConsumer> |> ignore
。
有点令人沮丧的是程序编译,所以我希望程序能够在该行的断点处停止,但它没有。
奇怪的是,如果我使用扩展方法的完整命名空间,那么断点就可以工作...
Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton<IHostedService, CommandConsumer>(services) |> ignore
Program.fs
中的源代码:
module Rm.Accounting.Workflows.Api.App
open System
open System.Threading
open System.Threading.Tasks
open System.IO
open Microsoft.AspNetCore.Builder
open Microsoft.AspNetCore.Hosting
open Microsoft.Extensions.Logging
open Microsoft.Extensions.DependencyInjection
open Giraffe
open Microsoft.AspNetCore.Http
open Microsoft.Extensions.Hosting
type CommandConsumer()=
inherit BackgroundService()
override __.ExecuteAsync(cancellationToken : CancellationToken) =
Task.CompletedTask
let webApp = choose [
GET >=>
choose [
route "/" >=> redirectTo false "/health"
]
setStatusCode 404 >=> text "Not Found" ]
let errorHandler (ex : Exception) (logger : ILogger) =
logger.LogError(ex, "An unhandled exception has occurred while executing the request.")
clearResponse >=> setStatusCode 500 >=> text ex.Message
let configureApp (app : IApplicationBuilder) =
app.UseHealthChecks(PathString("/health")) |> ignore
let env = app.ApplicationServices.GetService<IHostingEnvironment>()
(match env.IsDevelopment() with
| true -> app.UseDeveloperExceptionPage()
| false -> app.UseGiraffeErrorHandler errorHandler)
.UseHttpsRedirection()
.UseStaticFiles()
.UseGiraffe(webApp)
let configureServices (services : IServiceCollection) =
// That line below stops the debugger if there a breakpoint.
// Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton<IHostedService, CommandConsumer>(services)
// |> ignore
// The line does not stop the debugger with a breakpoint while the one above can, weird.
services.AddSingleton<IHostedService, CommandConsumer> |> ignore
services.AddHealthChecks() |> ignore
services.AddGiraffe() |> ignore
let configureLogging (builder : ILoggingBuilder) =
builder.AddFilter(fun l -> l.Equals LogLevel.Error)
.AddConsole()
.AddDebug() |> ignore
[<EntryPoint>]
let main _ =
let contentRoot = Directory.GetCurrentDirectory()
let webRoot = Path.Combine(contentRoot, "WebRoot")
WebHostBuilder()
.UseKestrel()
.UseContentRoot(contentRoot)
.UseIISIntegration()
.UseWebRoot(webRoot)
.Configure(Action<IApplicationBuilder> configureApp)
.ConfigureServices(configureServices)
.ConfigureLogging(configureLogging)
.Build()
.Run()
0
第services.AddSingleton<IHostedService, CommandConsumer> |> ignore
行是语法错误,你把涉及的类型分解一下就知道了。
services.AddSingleton<IHostedService, CommandConsumer>
是 Func<unit, IServiceCollection>
,意味着它是一个尚未被调用的函数。
ignore
然后接收该函数但不对其进行任何操作。
为了将单例注册到服务,您实际需要的语法是 services.AddSingleton<IHostedService, CommandConsumer>() |> invoke
,意思是“执行 AddSingleton 调用并忽略 return 值。
您可以使用 services.AddHostedService(CommandConsumer) |> ignore
而不是 services.AddSingleton<IHostedService, CommandConsumer>() |> ignore
,并且 CommandConsumer
将存在于托管后台服务的单例中。有关该主题的讨论,请参阅