在我的ASP.Net Core应用程序中,我需要在ConfigureServices
方法中注入一些依赖项(在我的例子中是一个存储库)。
问题是该方法不允许使用多个参数来注入依赖项。该怎么办?
这是我的代码
public void ConfigureServices(IServiceCollection services)
{
services.AddOptions();
// ...
services.AddSingleton<ITableRepositories, TableClientOperationsService>();
// Add framework services.
services.AddOpenIdConnect(options =>
{
// options.ClientId = ...
options.Events = new OpenIdConnectEvents
{
OnTicketReceived = async context =>
{
var user = (ClaimsIdentity)context.Principal.Identity;
if (user.IsAuthenticated)
{
// ...
// vvv
// HERE, I need the ITableRepositories repository;
// vvv
var myUser = await repository.GetAsync<Connection>(userId);
// ...
}
return;
}
};
});
}
如何在此处注入依赖项?
编辑:
遵循克里斯的想法(吼叫),这似乎有效:
public class Startup
{
// private repository, used in ConfigureServices, initialized in Startup
ITableRepositories repository;
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
// ... etc etc
Configuration = builder.Build();
// init repository here
this.repository = new TableClientOperationsService();
}
答案 0 :(得分:7)
您可以通过当前上下文的HttpContext.RequestServices
访问服务容器。
public void ConfigureServices(IServiceCollection services) {
services.AddOptions();
// ...
services.AddSingleton<ITableRepositories, TableClientOperationsService>();
// Add framework services.
services.AddOpenIdConnect(options => {
// options.ClientId = ...
options.Events = new OpenIdConnectEvents {
OnTicketReceived = async context => {
var user = (ClaimsIdentity)context.Principal.Identity;
if (user.IsAuthenticated) {
// ...
// get the ITableRepositories repository
var repository = context.HttpContext.RequestServices.GetService<ITableRepositories>();
var myUser = await repository.GetAsync<Connection>(userId);
// ...
}
return;
}
};
});
}
从技术上讲,您不需要访问ConfigureServices
中的依赖项,因为内联表达式可以被提取到自己的函数中。
public void ConfigureServices(IServiceCollection services) {
services.AddOptions();
// ...
services.AddSingleton<ITableRepositories, TableClientOperationsService>();
// Add framework services.
services.AddOpenIdConnect(options => {
// options.ClientId = ...
options.Events = new OpenIdConnectEvents {
OnTicketReceived = TicketReceived
};
});
}
private async Task TicketReceived(TicketReceivedContext context) {
var user = (ClaimsIdentity)context.Principal.Identity;
if (user.IsAuthenticated) {
// ...
// get the ITableRepositories repository
var repository = context.HttpContext.RequestServices.GetService<ITableRepositories>();
var myUser = await repository.GetAsync<Connection>(userId);
// ...
}
return;
}
答案 1 :(得分:1)
嗯,你不能。但是,您可以使用StartUp
构造函数来设置可在ConfigureServices
中使用的一个或多个属性。例如:
public StartUp(IHostingEnvironment env)
{
...
FooInstance = new Foo();
}
public IFoo FooInstance { get; }
public void ConfigureServices(IServiceCollection services)
{
// you can now use `Foo` here, without injecting it.
}
编辑(基于添加到问题的代码)
在这个特定的场景中,特别是因为这是一个单例,你可以简单地手动创建一个实例,然后绑定到该实例而不是泛型类型。例如:
var repository = new TableClientOperationsService();
services.AddSingleton<ITableRepositories>(repository);
然后,您可以直接在下面的代码中直接使用此变量:
var myUser = await repository.GetAsync<Connection>(userId);