c# ASP.. NET Core的替代扩展方法来注册服务



我有一个问题与我的AspNet Core应用程序,我有一个扩展方法注册配置,在一个外部库,如在示例中:

public static AuthenticationBuilder AddSaml2PIdP(this AuthenticationBuilder builder, SamlSettings settings)
{

foreach (var idP in settings.IdPs)
{
builder.AddSaml2p(idP.Scheme, options =>
{
options.ServiceProviderOptions = SpOptionsHelper.GetSpOptions(settings);
....
}
}
return builder;
}

和在Startup类中,在ConfigureServices中,我这样调用这个方法:

var samlSettings = _configuration.GetSection(SamlSettings.SamlSection).Get<SamlSettings>();
services.AddAuthentication()
.AddSaml2PIdP(samlSettings);

现在不幸的是,我不得不做一些改变,所以我需要注入依赖关系,以便能够在该类中执行其他操作,所以我不能再使用静态类或扩展方法,我应该这样做:

public class Saml2PExtension
{
private readonly IServiceScopeFactory _serviceScopeFactory;
public Saml2PExtension(IServiceScopeFactory serviceScopeFactory)
{
_serviceScopeFactory = serviceScopeFactory;
}
public void AddSaml2PIdP()
{
using var scope = _serviceScopeFactory.CreateScope();
var settings = scope.ServiceProvider.GetRequiredService<SamlSettings>();
var metadataParser = scope.ServiceProvider.GetRequiredService<ISamlMetadataParser>();
var environment = scope.ServiceProvider.GetRequiredService<IWebHostEnvironment>();
var builder = scope.ServiceProvider.GetRequiredService<AuthenticationBuilder>();
foreach (var idP in settings.IdPs)
{
builder.AddSaml2p(idP.Scheme, options =>
{
options.ServiceProviderOptions = SpOptionsHelper.GetSpOptions(settings);
....
}
}
}
}

但是我应该如何在ConfigureServices方法中注册这个类并调用configure方法?
使用新的实现,我不是使用ServiceProvider作为ServiceLocator反模式吗?
也欢迎能够以更优雅的方式解决问题的替代解决方案。
谢谢你

** EDIT **

最后,我选择保留第一个核心代码片段,将IWebHostEnvironment参数添加到扩展方法并手动实例化SamlMetadataParser,如下所示:
public static AuthenticationBuilder AddSaml2PIdP(this AuthenticationBuilder builder, IWebHostEnvironment environment, SamlSettings settings)
{
var metadataParser = new SamlMetadataParser(new ...); // manually create object

foreach (var idP in settings.IdPs)
{
builder.AddSaml2p(idP.Scheme, options =>
{
options.ServiceProviderOptions = SpOptionsHelper.GetSpOptions(settings);

// Read metadata from file ...
var idPOptions = metadataParser.Pars(xml);
........
}
}
return builder;
}

既然我在作文根,我认为这种方法是正确的。
谢谢你的帮助

这可以通过构建您自己的(只使用一次)容器来获取您注册的服务。您可以保留您的扩展方法,因为我们有一个通过AuthenticationBuilder暴露的IServiceCollection,这非常方便:

public static AuthenticationBuilder AddSaml2PIdP(this AuthenticationBuilder builder, 
SamlSettings settings)
{
using var scope = builder.Services.BuildServiceProvider().CreateScope();

//get the services
var settings = scope.ServiceProvider.GetRequiredService<SamlSettings>();
var metadataParser = scope.ServiceProvider.GetRequiredService<ISamlMetadataParser>();
var environment = scope.ServiceProvider.GetRequiredService<IWebHostEnvironment>();
var builder = scope.ServiceProvider.GetRequiredService<AuthenticationBuilder>();

//start using the services
foreach (var idP in settings.IdPs)
{
builder.AddSaml2p(idP.Scheme, options =>
{
options.ServiceProviderOptions = SpOptionsHelper.GetSpOptions(settings);
....
}
}
return builder; 
}

请注意,这是可能的,但你需要关心你所使用的服务所需的所有依赖项的注册顺序。实际上,您可以将AddAuthentication放在ConfigureServices的末尾,以确保它总是成功的。但是,如果有任何错误,将抛出异常,我们可以相应地调整顺序。

:

关于在IdentityServer4中可能与IdpOptions一起使用的后配置(用于OP尝试):

services.AddOptions<IdpOptions>()
.Configure((IdpOptions o, 
SamlSettings settings, 
ISamlMetadataParser metadataParser,
IWebHostEnvironment environment,
AuthenticationBuilder builder) => {
//use your services here to configure next ...
});

实际上上面使用了OptionsBuilder,它支持最多注入5个依赖项。您可以使用一个单独的类来实现IConfigureOptions<IdpOptions>IPostConfigureOptions<IdpOptions>。然后用services.ConfigureOptions<TImplementation>()配置它。

相关内容

  • 没有找到相关文章

最新更新