如何使用ASP.NET Core Dependency Injection应用装饰器

Mig*_*ura 18 c# dependency-injection inversion-of-control asp.net-core

在ASP.NET MVC 5应用程序上,我有以下StructureMap配置:

cfg.For(typeof(IRequestHandler<,>)).DecorateAllWith(typeof(MediatorPipeline<,>));
Run Code Online (Sandbox Code Playgroud)

有谁知道如何使用ASP.NET Core IOC进行此配置?

Tse*_*eng 14

开箱即用的IoC容器不支持装饰模式或自动发现,据我所知,这是"按设计".

我们的想法是提供一个开箱即用的基本IoC结构,或者可以插入其他IoC容器以扩展默认功能.

因此,如果您需要任何高级功能(支持特定构造函数,自动注册实现接口或注入装饰器和拦截器的所有类型),您必须自己编写或使用提供此功能的IoC容器.


Viv*_*Dev 6

使用检查员。只需安装nuget包,然后执行以下操作。

services.AddSingleton<IGreeter, Greeter>();
services.Decorate<IGreeter, GreeterLogger>();
services.Decorate<IGreeter, GreeterExceptionHandler>();
Run Code Online (Sandbox Code Playgroud)

顺序很重要。在上面,GreeterLogger 装饰了 Greeter。而 GreeterExceptionHandler 装饰了 GreeterLogger。

如果您需要更多信息,请查看thisthis


小智 5

解决方法不会将装饰器应用于类型的所有实例,而是使用扩展方法将装饰器逻辑抽象到另一个文件中。

定义装饰器结构,如:

public static class QueryHandlerRegistration
{
    public static IServiceCollection RegisterQueryHandler<TQueryHandler, TQuery, TResult>(
        this IServiceCollection services) 
        where TQuery : IQuery<TResult>
        where TQueryHandler : class, IQueryHandler<TQuery, TResult>
    {
        services.AddTransient<TQueryHandler>();
        services.AddTransient<IQueryHandler<TQuery, TResult>>(x =>
            new LoggingDecorator<TQuery, TResult>(x.GetService<ILogger<TQuery>>(), x.GetService<TQueryHandler>()));
        return services;
    }
}
Run Code Online (Sandbox Code Playgroud)

并称之为:

services.AddMvc();
// Add application services.
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddTransient<ISmsSender, AuthMessageSender>();

services.RegisterQueryHandler<FindThingByIdQueryHandler, FindThingByIdQuery, Thing>();
Run Code Online (Sandbox Code Playgroud)

还有正在开发的Scrutor包。

  • Scrutor 的提及非常有用。那里的图书馆不错。令人印象深刻的是,他们成功地使用描述符类的标准注册创建了整个机制。 (2认同)
  • 请注意,当 DI 范围结束时,Scrutor 当前不支持对装饰对象调用 Dispose。我为此在 GitHub 上提交了一个问题,希望他们最终能解决它:https://github.com/khellang/Scrutor/issues/91 (2认同)

sic*_*ich 5

在我的博文中,我描述了一个相对简单的扩展方法如何轻松解决这个问题。这是该帖子中的一个示例,它显示了装饰器配置的样子:

services.AddDecorator<IEmailMessageSender, EmailMessageSenderWithRetryDecorator>(decorateeServices =>
    {
        decorateeServices.AddScoped<IEmailMessageSender, SmtpEmailMessageSender>();
    });
Run Code Online (Sandbox Code Playgroud)