将 asp.net 个核心中间件从库内部注入到特定位置

Inject asp.net core middleware from inside a library to a specific location

我正在开发一个插件,我需要向用户注入另一个中间件StartUp.cs,有没有不修改用户的方法StartUp.cs?

我能想到的唯一方法实际上是修补运行时并将所需的 IL 指令注入到首先调用我的中间件的 UseXaf 中间件的开头。但是我希望它有内置机制。

if(env.IsDevelopment()) {
    app.UseDeveloperExceptionPage();
}
else {
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();

//INJECT IT HERE <---------

app.UseXaf();

您可以创建自己的自定义中间件 class。这可以通过实现 IMiddleware 接口或仅使用名为 InvokeInvokeAsync 的 public 方法创建 class。要将中间件添加到您的管道中,您可以创建一个静态方法,如下所示:

public static IApplicationBuilder UseCustomMiddleware(this IApplicationBuilder builder)
{
    return builder.UseMiddleware<CustomMiddleware>();
}

然后在 Startup.cs:

app.UseCustomMiddleware();

有关中间件的详细信息,请参阅 this page

我的解决方案是实际修补运行时并注入指令以在 UseXaf 中间件之前调用我的自定义中间件。

使用 https://github.com/pardeike/Harmony 库可以轻松完成:

    public class UseHangfire : IStartupFilter {
        private static readonly Harmony Harmony=new Harmony(nameof(UseHangfire));
        static UseHangfire() {
            var methodInfo = typeof(StartupExtensions).Method(nameof(StartupExtensions.UseXaf),Flags.StaticPublic);
            Harmony.Patch(methodInfo,postfix:new HarmonyMethod(typeof(UseHangfire),nameof(UseXaf))); //runtime patching of the UseXaf middleware
        }

        public static void UseXaf(IApplicationBuilder builder) => Dashboard?.Invoke(builder); //inject the Hangfire Dashboard and authorize before UseXaf is used

        public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next) => next;

        public static Action<IApplicationBuilder> Dashboard = builder 
            => builder.UseHangfireDashboard(options:new DashboardOptions {Authorization = new[] {new DashboardAuthorization()}
        });
    }

    public class DashboardAuthorization : IDashboardAuthorizationFilter {
        public bool Authorize(DashboardContext context)
            => context.GetHttpContext().User.Identity.IsAuthenticated;
    }

    public class HangfireStartup : IHostingStartup{
        public void Configure(IWebHostBuilder builder) 
            => builder.ConfigureServices(services => services
                .AddSingleton<IStartupFilter, UseHangfire>()
            );
    }

在剥离的代码片段中你可以看到我是如何使用 asp.net 核心 IHostingStartup inside my library to register an IStartupFilter 的,它又在运行时修补 UseXaf 中间件(使用 OHarmony库)在我需要的确切位置调用 UseHangfireDashboard 中间件。

用英语描述比在 C# 中输入更难:)

注意事项:根据实际想要修补的内容,您应该知道编译器可能会针对不同的框架内联或不内联它。在他们的维基上阅读更多内容 Inlining