在 ASP.NET Core MVC AddControllers 配置期间注册服务

Age*_*dum 2 c# asp.net-core-mvc asp.net-core

我正在制作一个可注入服务(即使用 IServiceCollection.AddSingleton 添加...),它与自定义全局操作过滤器一起使用。换句话说,我需要添加过滤器:

services.AddControllers(mvcOptions =>
{
   mvcOptions.Filters.Add<MyActionFilter>();
});
Run Code Online (Sandbox Code Playgroud)

但我还需要注册我的组件:

services.AddSingleton<IMyService, MyService>();
Run Code Online (Sandbox Code Playgroud)

这一切都很好。但是,现在我需要将此注册打包以便在多个项目中重复使用。为此,我想制作一个小助手,可以执行我所有的注册,例如:

services.AddControllers(mvcOptions =>
{
   mvcOptions.AddMyService(services);
});
// or
services.AddMyService();
Run Code Online (Sandbox Code Playgroud)

基本上,此注册的使用者不需要关心操作过滤器和我的服务的关系——只需要关心我的服务可以通过依赖注入来解析。

问题是,AddControllers 中的回调在图表构建后被调用,因此在该上下文中添加我的服务没有帮助。但我也无法在 AddControllers 回调范围之外添加我的操作过滤器(据我所知)。

有没有一种方法可以完成我想要做的事情,而不是需要我的消费者调用两个注册方法?

谢谢!

Kir*_*kin 7

选项1:

AddControllers支持多次调用,因此您的IServiceCollection扩展可以像这样简单:

services.AddSingleton<IMyService, MyService>();

services.AddControllers(mvcOptions =>
{
    mvcOptions.Filters.Add<MyActionFilter>();
});
Run Code Online (Sandbox Code Playgroud)

选项2:

如果您只想注册过滤器和服务并假设消费者调用AddControllers,您的IServiceCollection扩展方法可能如下所示:

services.AddSingleton<IMyService, MyService>();

services.Configure<MvcOptions>(mvcOptions =>
{
    mvcOptions.Filters.Add<MyActionFilter>();
});
Run Code Online (Sandbox Code Playgroud)

选项 3:

您可以创建一个扩展IMvcBuilder,允许消费者编写如下内容:

services.AddControllers()
    .AddMyService();
Run Code Online (Sandbox Code Playgroud)

为了支持这一点,请使用以下扩展方法:

public static class MvcBuilderExtensions
{
    public static IMvcBuilder AddMyService(this IMvcBuilder mvcBuilder)
    {
        mvcBuilder.Services.AddSingleton<IMyService, MyService>();

        mvcBuilder.AddMvcOptions(mvcOptions =>
        {
            mvcOptions.Filters.Add<MyActionFilter>();
        });

        return mvcBuilder;
    }
}
Run Code Online (Sandbox Code Playgroud)