Use a factory pattern. The factory lets you activate a service per request. Store the URL in a database table and fetch the URL during the request.
Custom Dependency injection in .NET 7
Hello all,
I have come across a scenario in our application where I have to initialize my services project with a URL. Earlier the URL was stored in configuration so we could pass the configuration variable while adding the services.
e.g.
builder.Services.AddTransient<Iservice,GethirdpartyServiceUrl(url from config)>
Now as per the new requirement, the users first need to select the url where they want to connect. So we need to pass the url from the application instead of configuration.
How can I initialize the services and intialize the service once user has selected an url?
I tried to create a middleware and passed the Servicecollection in middleware and inject the url from session. It fails with below error
InvalidOperationException: The service collection cannot be modified because it is read-only.
Could you please suggest a solution ?
Developer technologies ASP.NET ASP.NET Core
2 answers
Sort by: Most helpful
-
-
Xinran Shen - MSFT 2,091 Reputation points
2023-08-22T03:20:44.62+00:00 Hi, @Amit Dimri
From your description, I think you can create an
enum
model contains all theUrl
which user need to select, Then use factory pattern to create your service. Here is a simple demo, Hope it can help you solve this issue.public enum MyUrl { //some url which user need UrlAAA, UrlBBB, }
service
public interface IMyService { string getUrl(); }
I'm assuming that each url has a different use, so I create instances for them all.
public class MyServiceUrlB : IMyService { public string getUrl() { return "UrlBBB"; } }
public class MyServiceUrlA : IMyService { public string getUrl() { return "UrlAAAAA"; } }
factory pattern interface and instance
public interface IMyServiceFactory { public IMyService GetUrl(MyUrl url); }
public class MyServiceFactory : IMyServiceFactory { private readonly IServiceProvider _serviceProvider; public MyServiceFactory(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } public IMyService GetUrl(MyUrl url) { switch (url) { case MyUrl.UrlAAA: return (IMyService)_serviceProvider.GetService(typeof(MyServiceUrlA)); case MyUrl.UrlBBB: return (IMyService)_serviceProvider.GetService(typeof(MyServiceUrlB)); default: throw new ArgumentOutOfRangeException(nameof(url), url, $"Shape of {url} is not supported."); } } }
Register them in
program.cs
filebuilder.Services.AddTransient<IMyServiceFactory, MyServiceFactory>(); builder.Services.AddScoped<MyServiceUrlA>().AddScoped<IMyService, MyServiceUrlA>(s => s.GetService<MyServiceUrlA>()); builder.Services.AddScoped<MyServiceUrlB>().AddScoped<IMyService, MyServiceUrlB>(s => s.GetService<MyServiceUrlB>())
register in controller
public class HomeController : Controller { //...... private readonly IMyServiceFactory _myServiceFactory; public HomeController(IMyServiceFactory myServiceFactory) { _myServiceFactory = myServiceFactory; } public string Url(MyUrl url) { var urlservice = _myServiceFactory.GetUrl(url); var result = urlservice.getUrl(); return result; } }
Now you can check it will initialize different service according to the url user select.
If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.
Best regards,
Xinran Shen