Instantiate a class object in startup.cs in .Net Core

7.6k Views Asked by At

I am trying to pass an interface and settings into a class while creating an instance of that class in startup.cs in .Net Core Project. I am using the below code to do so. I have some code written in the constructor of Student class but while starting the application the Code/Logic inside the constructor is not working. There is no error but the debug pointer is not hitting the constructor of Student class.

services.AddSingleton(c => new Student(settings, resourceSetting, c.GetService<IPersonService>()));

If I am using the below code then the code inside Student constructor is working fine.

 Student studentHandler = new Student(settings, resourceSetting,);
 services.AddSingleton<Student>(studentHandler);

But I need to pass Service interface in the constructor to do some work while starting the Project. Can anyone help me with what I am missing here?

2

There are 2 best solutions below

0
On BEST ANSWER

the debug pointer is not hitting the constructor of Student class

That's because you're registering the type as an implementation factory in the first snippet, using AddSingleton<TService> (this IServiceCollection services, Func<IServiceProvider,TService> implementationFactory) With this method, the implementation factory delegate (and subsequently the Student constructor) won't be called until the dependency is resolved.

In the second snippet, you're directly instantiating the type at service registration and adding that instance to the service collection with AddSingleton<TService> (this IServiceCollection services, TService implementationInstance).


Here's an example with logs explaining each step in each approach:

class Program
{
    static void Main(string[] args)

    {
        RegisterImplementationFactory();
        RegisterImplementation();
    }

    static void RegisterImplementationFactory()
    {
        Console.WriteLine("RegisterImplementationFactory ------------");

        var services = new ServiceCollection();

        Console.WriteLine("Registering Student...");
        services.AddSingleton(c => new Student());
        Console.WriteLine("Student registered.");

        Console.WriteLine("Building ServiceProvider...");
        var serviceProvider = services.BuildServiceProvider();
        Console.WriteLine("ServiceProvider built.");

        Console.WriteLine("Resolving Student...");
        Student student = serviceProvider.GetService<Student>();
        Console.WriteLine("Student resolved.");

        Console.WriteLine("RegisterImplementationFactory ------------");
        Console.WriteLine();
    }

    static void RegisterImplementation()
    {
        Console.WriteLine("RegisterImplementation ------------");

        var services = new ServiceCollection();

        Console.WriteLine("Registering Student...");
        Student studentToRegister = new Student();
        services.AddSingleton(studentToRegister);
        Console.WriteLine("Student registered.");

        Console.WriteLine("Building ServiceProvider...");
        var serviceProvider = services.BuildServiceProvider();
        Console.WriteLine("ServiceProvider built.");

        Console.WriteLine("Resolving Student...");
        Student student = serviceProvider.GetService<Student>();
        Console.WriteLine("Student resolved.");

        Console.WriteLine("RegisterImplementation ------------");
        Console.WriteLine();
    }
}

class Student
{
    public Student()
    {
        Console.WriteLine("!!! Instantiating Student...");
    }
}

The output of this is:

RegisterImplementationFactory ------------
Registering Student...
Student registered.
Building ServiceProvider...
ServiceProvider built.
Resolving Student...
!!! Instantiating Student...
Student resolved.
RegisterImplementationFactory ------------

RegisterImplementation ------------
Registering Student...
!!! Instantiating Student...
Student registered.
Building ServiceProvider...
ServiceProvider built.
Resolving Student...
Student resolved.
RegisterImplementation ------------

With this you can clearly see that when registering using the factory delegate, the Student constructor isn't called until the type is resolved (with GetService<Student>() in this case).

0
On

It seems you are using Dependency Injection, so I would recommend based on your constructor to further make use of the DI engine.

First, you will want to register the settings and resourceSetting objects

services.AddSingleton<Student>(settings);
services.AddSingleton<Student>(resourceSetting);

Then register your Student class as well

services.AddSingleton<Student>();

And now once you build your ServiceCollection into the ServiceProvider via .BuildServiceProvider(); (If you are doing a console app) you can call:

var myStudent = myServiceProvider.GetRequiredService<Student>();

If you are doing this in something like asp.net, then you would simply just inject your Student class into a controller or other such service for consumption

class MyController : ControllerBase
{

    private Student Student { get; }

    public MyController(Student student)
    {
       Student = student ?? throw new ArgumentNullException(nameof(student));
    }
 
    ...
}