Custom Dependency injection in .NET 7

Amit Dimri 56 Reputation points
2023-08-21T13:36:36.7966667+00:00

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
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. AgaveJoe 30,126 Reputation points
    2023-08-21T13:50:50.59+00:00

    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.

    Dependency injection in ASP.NET Core

    Dependency injection guidelines

    0 comments No comments

  2. 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 the Url 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 file

    builder.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.

    enter image description here

    User's image


    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


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.