我有一个Service Fabric asp.net核心无状态服务,它实现了自定义中间件。在该中间件中,我需要访问我的服务实例。我将如何使用asp.net core的内置DI / IoC系统进行注入?
public class MyMiddleware
{
private readonly RequestDelegate _next;
public MyMiddleware(RequestDelegate next)
{
_next = next;
}
public Task Invoke(HttpContext httpContext)
{
// ** need access to service instance here **
return _next(httpContext);
}
}
有人提到使用Service Fabric团队在Apr 20, 2017 Q&A #11 [45:30]的Web Api 2中使用TinyIoC来完成此任务。同样,目前推荐的方法是使用asp.net核心。
非常感谢任何帮助或示例!
答案 0 :(得分:5)
在创建ServiceInstanceListener
的asp.net核心无状态服务中,您可以像这样注入上下文:
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return new[]
{
new ServiceInstanceListener(serviceContext =>
new WebListenerCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
{
logger.LogStatelessServiceStartedListening<WebApi>(url);
return new WebHostBuilder().UseWebListener()
.ConfigureServices(
services => services
.AddSingleton(serviceContext) // HERE IT GOES!
.AddSingleton(logger)
.AddTransient<IServiceRemoting, ServiceRemoting>())
.UseContentRoot(Directory.GetCurrentDirectory())
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
.UseStartup<Startup>()
.UseUrls(url)
.Build();
}))
};
}
你的中间件可以像这样使用它:
public class MyMiddleware
{
private readonly RequestDelegate _next;
public MyMiddleware(RequestDelegate next)
{
_next = next;
}
public Task Invoke(HttpContext httpContext, StatelessServiceContext serviceContext)
{
// ** need access to service instance here **
return _next(httpContext);
}
}
有关完整示例,请查看此存储库:https://github.com/DeHeerSoftware/Azure-Service-Fabric-Logging-And-Monitoring
您的兴趣点:
答案 1 :(得分:2)
通过构造函数的依赖注入适用于中间件类以及其他类。只需将其他参数添加到中间件构造函数
即可public MyMiddleware(RequestDelegate next, IMyService myService)
{
_next = next;
...
}
但也可以直接向Invoke
方法
Documentation:因为中间件是在app启动时构建的,而不是按请求构建的,所以中间件构造函数使用的作用域生存期服务在每次请求期间都不会与其他依赖注入的类型共享。如果必须在中间件和其他类型之间共享作用域服务,请将这些服务添加到Invoke方法的签名中。
Invoke
方法可以接受依赖注入填充的其他参数。
public class MyMiddleware
{
private readonly RequestDelegate _next;
public MyMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext httpContext, IMyScopedService svc)
{
svc.MyProperty = 1000;
await _next(httpContext);
}
}