title: C# ASP.NET Core alternative to an extension method to register services
body: <p>I have a problem with my AspNet Core application, I had an extension method to register configurations, on an external library, as in the example:</p>
  <pre><code>public static AuthenticationBuilder AddSaml2PIdP(this AuthenticationBuilder builder, SamlSettings settings)
  {
             
      foreach (var idP in settings.IdPs)
      {
          builder.AddSaml2p(idP.Scheme, options =&gt;
          {
               options.ServiceProviderOptions = SpOptionsHelper.GetSpOptions(settings);
               ....
          }
      }
      return builder;
  }
  </code></pre>
  <p>and in Startup class, in ConfigureServices i call this method like this:</p>
  <pre><code>var samlSettings = _configuration.GetSection(SamlSettings.SamlSection).Get&lt;SamlSettings&gt;();
  services.AddAuthentication()
      .AddSaml2PIdP(samlSettings);
  </code></pre>
  <p>Now unfortunately I had to make some changes, so I need to inject dependencies to be able to perform other operations in that class, so I can no longer use neither a static class nor an extension method, I should do something like this:</p>
  <pre><code>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&lt;SamlSettings&gt;();
          var metadataParser = scope.ServiceProvider.GetRequiredService&lt;ISamlMetadataParser&gt;();
          var environment = scope.ServiceProvider.GetRequiredService&lt;IWebHostEnvironment&gt;();
          var builder = scope.ServiceProvider.GetRequiredService&lt;AuthenticationBuilder&gt;();
  
          foreach (var idP in settings.IdPs)
          {
              builder.AddSaml2p(idP.Scheme, options =&gt;
              {
                  options.ServiceProviderOptions = SpOptionsHelper.GetSpOptions(settings);
                  ....
              }
          }
  
      }
  }
  </code></pre>
  <p>But how should I register this class in the ConfigureServices method and have the configure method called?<br />
  Using the new implementation, am I not using the ServiceProvider as the ServiceLocator antipattern?<br />
  Alternative solutions are also welcome that could solve the problem in a more elegant way.<br />
  Thank you</p>
  <p>** EDIT **</p>
  <p>In the end, I chose to keep the first core code snippet, added the IWebHostEnvironment parameter to the extension method and instantiated SamlMetadataParser manually, like this:</p>
  <pre><code>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 =&gt;
          {
               options.ServiceProviderOptions = SpOptionsHelper.GetSpOptions(settings);
               
               // Read metadata from file ...
               var idPOptions = metadataParser.Pars(xml);
               ........
          }
      }
      return builder;
  }
  </code></pre>
  <p>Since I am in the composition root, I think this approach is correct.<br />
  Thanks anyway for the help</p>