ASP.NET Core 5 - 如何拥有可选依赖项?
ASP.NET Core 5 - How to have optional dependencies?
我正在开发一个中间件,我希望它具有对内部日志记录库的可选依赖性。换句话说,如果 MyLoggingService
已注册,太棒了!否则,生活将继续,我将登录到控制台。
但是通过声明 public async Task Invoke(HttpContext httpContext, MyLoggingService logger)
,我收到一个运行时错误,提示它未注册。我尝试将默认值设置为 null
但这没有用。另外,因为它是一个中间件,我不能重载 Invoke
方法。
除了请求服务集合,自己解决依赖,还有其他解决方案吗?
与其将依赖项设为可选,不如考虑:
- 抽象编程,例如
IMyLoggingService
- 注册一个Null Object实现
例如:
public class CustomMiddleware1 : IMiddleware
{
private readonly IMyLoggingService logger;
public CustomMiddleware1(IMyLoggingService logger) => this.logger = logger;
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
this.logger.Log("Before");
await next(context);
this.logger.Log("After");
}
}
空对象实现:
public sealed class NullMyLoggingService : IMyLoggingService
{
public void Log(LogEntry e) { }
}
注册人数:
services.AddSingleton<IMyLoggingService>(new NullMyLoggingService());
app.Use<CustomMiddleware1>();
对 AddSingleton<IMyLoggingService>(new NullMyLoggingService())
的调用确保 IMyLoggingService
的注册始终存在。这防止了消费者的复杂性,否则他们将不得不为记录器不存在的情况添加条件逻辑。
可以通过简单地在第一个之后添加第二个 IMyLoggingService
来替换此空实现:
services.AddScoped<IMyLoggingService, DbMyLoggingService>();
app.Use<CustomMiddleware1>();
答案非常简单:
public async Task Invoke(HttpContext httpContext, MyLoggingService logger = null)
我正在开发一个中间件,我希望它具有对内部日志记录库的可选依赖性。换句话说,如果 MyLoggingService
已注册,太棒了!否则,生活将继续,我将登录到控制台。
但是通过声明 public async Task Invoke(HttpContext httpContext, MyLoggingService logger)
,我收到一个运行时错误,提示它未注册。我尝试将默认值设置为 null
但这没有用。另外,因为它是一个中间件,我不能重载 Invoke
方法。
除了请求服务集合,自己解决依赖,还有其他解决方案吗?
与其将依赖项设为可选,不如考虑:
- 抽象编程,例如
IMyLoggingService
- 注册一个Null Object实现
例如:
public class CustomMiddleware1 : IMiddleware
{
private readonly IMyLoggingService logger;
public CustomMiddleware1(IMyLoggingService logger) => this.logger = logger;
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
this.logger.Log("Before");
await next(context);
this.logger.Log("After");
}
}
空对象实现:
public sealed class NullMyLoggingService : IMyLoggingService
{
public void Log(LogEntry e) { }
}
注册人数:
services.AddSingleton<IMyLoggingService>(new NullMyLoggingService());
app.Use<CustomMiddleware1>();
对 AddSingleton<IMyLoggingService>(new NullMyLoggingService())
的调用确保 IMyLoggingService
的注册始终存在。这防止了消费者的复杂性,否则他们将不得不为记录器不存在的情况添加条件逻辑。
可以通过简单地在第一个之后添加第二个 IMyLoggingService
来替换此空实现:
services.AddScoped<IMyLoggingService, DbMyLoggingService>();
app.Use<CustomMiddleware1>();
答案非常简单:
public async Task Invoke(HttpContext httpContext, MyLoggingService logger = null)