簡體   English   中英

C# ASP.NET 核心替代擴展方法來注冊服務

[英]C# ASP.NET Core alternative to an extension method to register services

我的 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;
}

在啟動 class 中,在 ConfigureServices 中我這樣調用此方法:

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

現在不幸的是我不得不進行一些更改,所以我需要注入依賴項才能在 class 中執行其他操作,所以我不能再使用 static class:也不能使用擴展方法

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 方法中注冊這個 class 並調用 configure 方法?
使用新的實現,我不是將 ServiceProvider 用作 ServiceLocator 反模式嗎?
也歡迎可以以更優雅的方式解決問題的替代解決方案。
謝謝

** 編輯 **

最后,我選擇保留第一個核心代碼片段,在擴展方法中添加 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>的單獨 class 。 然后只需使用services.ConfigureOptions<TImplementation>()對其進行配置。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM