ASP.Net 核心 RouteBuilder 和依赖注入

ASP.Net Core RouteBuilder and Dependency Injection

我正在 ASP.NET Core 2.0 中试验路由。我有一个 class 包装了 System.DateTime.UtcNow 功能(用于更简单的单元测试)

public interface IDateTimeWrapper
{
    DateTime UtcNow();
}

public sealed class DateTimeWrapper : IDateTimeWrapper
{
    public DateTime UtcNow()
    {
        return DateTime.UtcNow;
    }
}

这由具有单一方法 Execute 的 class 使用,该方法将 DateTimeWrapper 的结果写入 HttpResponse

public class WhatIsTheTimeHandler
{
    private readonly IDateTimeWrapper _dateTimeWrapper;

    public WhatIsTheTimeHandler(
        IDateTimeWrapper dateTimeWrapper)
    {
        this._dateTimeWrapper = dateTimeWrapper;
    }

    public async Task Execute(Microsoft.AspNetCore.Http.HttpContext httpContext)
    {
        httpContext.Response.StatusCode = 200;            
        await httpContext.Response.WriteAsync(this._dateTimeWrapper.UtcNow().ToString());
    }
}

Startup 中,我希望 /whatisthetime/ 的任何请求都由 WhatIsTheTimeHandler 处理(参见 !!! 评论)。

public sealed class Startup
{
    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder();

        builder.SetBasePath(env.ContentRootPath);
        builder.AddJsonFile("appsettings.json", false, true);
        // we must lowercase the json file path due to linux file name case sensitivity
        builder.AddJsonFile($"appsettings.{env.EnvironmentName.ToLower()}.json", false, true);
        builder.AddEnvironmentVariables();

        this.Configuration = builder.Build();
    }

    public IConfigurationRoot Configuration { get; set; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddRouting();

        services.AddScoped<IDateTimeWrapper, DateTimeWrapper>();
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        loggerFactory.AddConsole();

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        var routeBuilder = new Microsoft.AspNetCore.Routing.RouteBuilder(app);

        // !!!
        // I want to do something like
        // routeBuilder.MapGet("whatisthetime", WhatIsTheTimeHandler.Execute);

        var routes = routeBuilder.Build();
        app.UseRouter(routes);
    }
}

我不能做上面我想做的,因为WhatIsTheTimeHandler.Execute是一个实例方法。 IE。错误:

An object reference is required for the non-static field, method or property 'WhatIsTheTimeHandler.Execute(HttpContext)' Cannot access non-static method in static context).

如果我做到了 static 那么我将无法使用 _dateTimeWrapper 实例成员。

有什么想法吗?

ASP.NET 核心路由将路由映射到委托。 ASP.NET MVC 核心路由将路由映射到对象(通常称为控制器)。所以后者可能是满足您特殊需求的更好解决方案。

但是,要使您当前的解决方案正常工作,您需要将处理程序添加为服务:

services.AddScoped<WhatIsTheTimeHandler>();

然后从路由中调用它,例如:

routeBuilder.MapGet("whatisthetime", async (context) => {
    await context.RequestServices.GetRequiredService<WhatIsTheTimeHandler>().Execute(context);
});