Sample code for the service lifecycle:

    public class ServiceA : IServiceA.IDisposable
    {
        private readonly int _n;
        public ServiceA(INumberService numberService)
        {
            _n = numberService.GetNumber();
            Console.WriteLine($"ctor {nameof(ServiceA)}, {_n}");
        }

        public void A() => Console.WriteLine($"{nameof(A)}, {_n}");
        public void Dispose() => Console.WriteLine($"disposing {nameof(ServiceA)}, {_n}");
    }
    
    public class ServiceB : IServiceB.IDisposable
    {
        private readonly int _n;
        public ServiceB(INumberService numberService)
        {
            _n = numberService.GetNumber();
            Console.WriteLine($"ctor {nameof(ServiceB)}, {_n}");
        }

        public void B() => Console.WriteLine($"{nameof(B)}, {_n}");
        public void Dispose() => Console.WriteLine($"disposing {nameof(ServiceB)}, {_n}");
    }
    
    public class ServiceC : IServiceC.IDisposable
    {
        private bool _isDisposed = false;
        private readonly int _n;
        public ServiceC(INumberService numberService)
        {
            _n = numberService.GetNumber();
            Console.WriteLine($"ctor {nameof(ServiceC)}, {_n}");
        }

        public void C()
        {
            if (_isDisposed)
                throw new ObjectDisposedException("ServiceC");

            Console.WriteLine($"{nameof(C)}, {_n}");
        }
        public void Dispose()
        {
            Console.WriteLine($"disposing {nameof(ServiceC)}, {_n}");
            _isDisposed = true;
        }
    }
    
    public class NumberService : INumberService
    {
        private int _number = 0;
        public int GetNumber() => Interlocked.Increment(ref _number);
    }

Copy the code

    public class ControllerX : IDisposable
    {
        private readonly IServiceA _serviceA;
        private readonly IServiceB _serviceB;
        private readonly int _n;
        private int _countm = 0;
        public ControllerX(IServiceA serviceA, IServiceB serviceB, INumberService numberService)
        {
            _n = numberService.GetNumber();
            Console.WriteLine($"ctor {nameof(ControllerX)}, {_n}");
            _serviceA = serviceA;
            _serviceB = serviceB;
        }

        public void M()
        {
            Console.WriteLine($"invoked {nameof(M)} for the {++_countm}. time");
            _serviceA.A();
            _serviceB.B();
        }

        public void Dispose() => Console.WriteLine($"disposing {nameof(ControllerX)}, {_n}");
    }
Copy the code
    public interface IServiceA
    {
        void A();
    }
    
    public interface IServiceB
    {
        void B();
    }
    
    public interface IServiceC
    {
        void C();
    }
    
    public interface INumberService
    {
        int GetNumber();
    }
Copy the code

Call the output of SingletonAndTransient()

    class Program 
    {
        static void Main()
        {
            SingletonAndTransient();
        }

        private static void SingletonAndTransient()
        {
            Console.WriteLine(nameof(SingletonAndTransient));

            ServiceProvider RegisterServices()
            {
                IServiceCollection services = new ServiceCollection();
                services.AddSingleton<IServiceA, ServiceA>();
                services.AddTransient<IServiceB, ServiceB>();
                // services.AddSingleton<ControllerX>();
                services.Add(new ServiceDescriptor(typeof(ControllerX), typeof(ControllerX), ServiceLifetime.Transient));
                services.AddSingleton<INumberService, NumberService>();
                return services.BuildServiceProvider();
            }

            using (ServiceProvider container = RegisterServices())
            {
                Console.WriteLine($"requesting {nameof(ControllerX)}");

                ControllerX x = container.GetRequiredService<ControllerX>();
                x.M();
                x.M();

                Console.WriteLine($"requesting {nameof(ControllerX)}"); ControllerX x2 = container.GetRequiredService<ControllerX>(); x2.M(); Console.WriteLine(); }}}Copy the code
SingletonAndTransient
requesting ControllerX
ctor ServiceA, 1
ctor ServiceB, 2
ctor ControllerX, 3
invoked M for the 1. time
A, 1
B, 2
invoked M for the 2. time
A, 1
B, 2
requesting ControllerX
ctor ServiceB, 4
ctor ControllerX, 5
invoked M for the 1. time
A, 1
B, 4

disposing ControllerX, 5
disposing ServiceB, 4
disposing ControllerX, 3
disposing ServiceB, 2
disposing ServiceA, 1
Copy the code

The output of the UsingScoped ()

    class Program 
    {
        static void Main()
        {
            UsingScoped();
        }

       
        private static void UsingScoped()
        {
            Console.WriteLine(nameof(UsingScoped));

            ServiceProvider RegisterServices()
            {
                var services = new ServiceCollection();
                services.AddSingleton<INumberService, NumberService>();
                services.AddScoped<IServiceA, ServiceA>();
                services.AddSingleton<IServiceB, ServiceB>();
                services.AddTransient<IServiceC, ServiceC>();
                return services.BuildServiceProvider();
            }

            using (ServiceProvider container = RegisterServices())
            {
                using (IServiceScope scope1 = container.CreateScope())
                {
                    IServiceA a1 = scope1.ServiceProvider.GetService<IServiceA>();
                    a1.A();
                    IServiceA a2 = scope1.ServiceProvider.GetService<IServiceA>();
                    a2.A();
                    IServiceB b1 = scope1.ServiceProvider.GetService<IServiceB>();
                    b1.B();
                    IServiceC c1 = scope1.ServiceProvider.GetService<IServiceC>();
                    c1.C();
                    IServiceC c2 = scope1.ServiceProvider.GetService<IServiceC>();
                    c2.C();
                }

                Console.WriteLine("end of scope1");

                using (IServiceScope scope2 = container.CreateScope())
                {
                    IServiceA a3 = scope2.ServiceProvider.GetService<IServiceA>();
                    a3.A();
                    IServiceB b2 = scope2.ServiceProvider.GetService<IServiceB>();
                    b2.B();
                    IServiceC c3 = scope2.ServiceProvider.GetService<IServiceC>();
                    c3.C();
                }
                Console.WriteLine("end of scope2"); Console.WriteLine(); }}}Copy the code
UsingScoped
ctor ServiceA, 1
A, 1
A, 1
ctor ServiceB, 2
B, 2
ctor ServiceC, 3
C, 3
ctor ServiceC, 4
C, 4
disposing ServiceC, 4
disposing ServiceC, 3
disposing ServiceA, 1
end of scope1
ctor ServiceA, 5
A, 5
B, 2
ctor ServiceC, 6
C, 6
disposing ServiceC, 6
disposing ServiceA, 5
end of scope2

disposing ServiceB, 2
Copy the code

The output of the CustomFactories ()

    class Program 
    {
        static void Main()
        {
            CustomFactories();
        }

        private static void CustomFactories()
        {
            Console.WriteLine(nameof(CustomFactories));

            IServiceB CreateServiceBFactory(IServiceProvider provider) =>
                new ServiceB(provider.GetService<INumberService>());

            ServiceProvider RegisterServices()
            {
                var numberService = new NumberService();

                var services = new ServiceCollection();
                services.AddSingleton<INumberService>(numberService);  // add existing

                services.AddTransient<IServiceB>(CreateServiceBFactory);  // use a factory
                services.AddSingleton<IServiceA, ServiceA>();
                returnservices.BuildServiceProvider(); } using (ServiceProvider container = RegisterServices()) { IServiceA a1 = container.GetService<IServiceA>(); IServiceA a2 = container.GetService<IServiceA>(); IServiceB b1 = container.GetService<IServiceB>(); IServiceB b2 = container.GetService<IServiceB>(); } Console.WriteLine(); }}Copy the code
CustomFactories
ctor ServiceA, 1
ctor ServiceB, 2
ctor ServiceB, 3
disposing ServiceB, 3
disposing ServiceB, 2
disposing ServiceA, 1
Copy the code

Service lifecycle:

  • Singletons: Always return the same instance
  • Transient: A new object is returned each time a service is injected. Each time a service is requested from the container, a new instance is created
  • Scoped: Always return the same instance from the same scope, different instance from different scope

Registration Services:

  • AddSingleton and AddTransient are both extensions to ServiceCollection to make it easier to register services. There is also a more primitive Add method, which is more difficult to use and can only be seen with IServiceCollection, but not with ServiceCollection
services.Add(new ServiceDescriptor(typeof(ControllerX), typeof(ControllerX), ServiceLifetime.Transient));
Copy the code

For the Scoped:

  • In ASP.NET Core Web applications, the default scope is an HTTP Web Request. When a Scoped service is requested from the container, the same instance is returned if the request is from the same HTTP Web Request. Instead, return a different instance. This allows easy sharing of state in HTTP Web Requests
  • For non-ASP.NET Core Web applications, you need to create your own scope

Release of services:

  • At the end of the scope, the Transient and scoped services are released automatically, but the Singleton is not released
  • When scoping is released, the Transient service and scoped service are released. The Singleton service is released when the root provider is released
  • Dispose does not need to be called on the service to release them. Dispose method is automatically called as long as the IDisposable interface is implemented
  • .NET Core 2.0 releases services in the reverse order of creation

Other instantiation methods:

  • Create a custom factory
IServiceB CreateServiceBFactory(IServiceProvider provider) =>
                new ServiceB(provider.GetService<INumberService>());
                
services.AddTransient<IServiceB>(CreateServiceBFactory); 
Copy the code
  • Pass the existing instance to the container
var numberService = new NumberService();

services.AddSingleton<INumberService>(numberService);
Copy the code