Memahami konsep Lifetime scope di Autofac

Maafkan saya, saya baru mempelajari Autofac. Saya memiliki beberapa masalah untuk memahami Lifetime scope di Autofac. Mohon bantuannya untuk mengulas dibawah ini.

Katakanlah kita memiliki kode di bawah ini.

using(var scope = container.BeginLifetimeScope())
{
  // Resolve services from a scope that is a child
  // of the root container.
  var service = scope.Resolve<IService>();

  // You can also create nested scopes...
  using(var unitOfWorkScope = scope.BeginLifetimeScope())
  {
    var anotherService = unitOfWorkScope.Resolve<IOther>();
  }
}

Sebagai Dokumen letakkan. Lifetime scopes are disposable and they track component disposal.

Apakah berarti service sekali pakai dan dapat didaur ulang oleh GC setelah pernyataan using(var scope = container.BeginLifetimeScope()) selesai?

Dan begitu juga dengan anotherService dalam lingkup bersarang? ?

Bagaimana saya dapat membuktikannya melalui suatu eksperimen?

Terima kasih.


person Joe.wang    schedule 14.12.2016    source sumber


Jawaban (1)


Saya rasa Anda harus terlebih dahulu memahami bahwa Autofac memungkinkan untuk mendaftarkan komponen dengan masa pakai berbeda:

  • Seumur hidup sementara, melalui InstancePerDependency, yang berarti container akan membuat instance baru setiap kali diminta untuk menyelesaikan suatu komponen
  • Per cakupan seumur hidup, melalui InstancePerLifetimeScope, yang berarti wadah akan menyelesaikan instance komponen yang sama dalam cakupan seumur hidup tertentu
  • Tunggalton, melalui SingleInstance. Dalam hal ini, paling banyak satu instance komponen dibuat oleh container

Jadi, apa yang dimaksud dengan jalur pembuangan komponen?

Artinya, setiap cakupan seumur hidup melacak komponen yang dimilikinya. Setelah cakupan seumur hidup dibuang, setiap komponen milik yang dapat dibuang - yaitu yang mengimplementasikan IDisposable - akan dibuang.

Jadi kapan komponen saya akan dibuang?

Kembali ke poin pertama, itu tergantung pada masa hidup mana mereka terdaftar.

  • Jika komponen didaftarkan dengan masa pakai sementara, semua instance akan dibuang ketika cakupan masa pakai pemiliknya dibuang

  • Jika sudah didaftarkan sebagai cakupan seumur hidup, maka satu instance akan dibuang ketika cakupan seumur hidup yang dimilikinya dibuang

  • Jika komponen telah didaftarkan sebagai singleton, instance tersebut dimiliki oleh cakupan umur akar, dan hanya akan dibuang ketika cakupan umur akar tersebut dibuang.

Beberapa kode pendukung

public class TransientService : IDisposable
{
    private static int _instanceCount = 0;
    private readonly int _instanceNumber;

    public TransientService()
    {
        _instanceCount++;
        _instanceNumber = _instanceCount;

        Console.WriteLine($"Just created TransientService #{_instanceNumber}");
    }

    public void Dispose()
    {
        Console.WriteLine($"Disposing TransientService #{_instanceNumber}");
    }
}

public class LifetimeScopeService : IDisposable
{
    private static int _instanceCount = 0;
    private readonly int _instanceNumber;

    public LifetimeScopeService()
    {
        _instanceCount++;
        _instanceNumber = _instanceCount;

        Console.WriteLine($"Just created LifetimeScopeService #{_instanceNumber}");
    }

    public void Dispose()
    {
        Console.WriteLine($"Disposing LifetimeScopeService #{_instanceNumber}");
    }
}

public class SingletonService : IDisposable
{
    private static int _instanceCount = 0;
    private readonly int _instanceNumber;

    public SingletonService()
    {
        _instanceCount++;
        _instanceNumber = _instanceCount;

        Console.WriteLine($"Just created SingletonService #{_instanceNumber}");
    }

    public void Dispose()
    {
        Console.WriteLine($"Disposing SingletonService #{_instanceNumber}");
    }
}

class Program
{
    static void Main(string[] args)
    {
        var builder = new ContainerBuilder();

        builder
            .RegisterType<TransientService>()
            .AsSelf()
            .InstancePerDependency();

        builder
            .RegisterType<LifetimeScopeService>()
            .AsSelf()
            .InstancePerLifetimeScope();

        builder
            .RegisterType<SingletonService>()
            .AsSelf()
            .SingleInstance();

        using (var container = builder.Build())
        {
            Console.WriteLine("Created the root scope");

            var rootTransientService = container.Resolve<TransientService>();
            var rootLifetimeScopeService = container.Resolve<LifetimeScopeService>();
            var rootSingletonService = container.Resolve<SingletonService>();

            var rootTransientServiceTwo = container.Resolve<TransientService>();
            var rootLifetimeScopeServiceTwo = container.Resolve<LifetimeScopeService>();
            var rootSingletonServiceTwo = container.Resolve<SingletonService>();

            using (var outerLifetimeScope = container.BeginLifetimeScope())
            {
                Console.WriteLine("Created the outer lifetime scope");

                var outerTransientService = outerLifetimeScope.Resolve<TransientService>();
                var outerLifetimeScopeService = outerLifetimeScope.Resolve<LifetimeScopeService>();
                var outerSingletonService = outerLifetimeScope.Resolve<SingletonService>();

                var outerTransientServiceTwo = outerLifetimeScope.Resolve<TransientService>();
                var outerLifetimeScopeServiceTwo = outerLifetimeScope.Resolve<LifetimeScopeService>();
                var outerSingletonServiceTwo = outerLifetimeScope.Resolve<SingletonService>();

                using (var innerLifetimeScope = container.BeginLifetimeScope())
                {
                    Console.WriteLine("Created the inner lifetime scope");

                    var innerTransientService = innerLifetimeScope.Resolve<TransientService>();
                    var innerLifetimeScopeService = innerLifetimeScope.Resolve<LifetimeScopeService>();
                    var innerSingletonService = innerLifetimeScope.Resolve<SingletonService>();

                    var innerTransientServiceTwo = innerLifetimeScope.Resolve<TransientService>();
                    var innerLifetimeScopeServiceTwo = innerLifetimeScope.Resolve<LifetimeScopeService>();
                    var innerSingletonServiceTwo = innerLifetimeScope.Resolve<SingletonService>();
                }

                Console.WriteLine("Disposed the inner lifetime scope");
            }

            Console.WriteLine("Disposed the outer lifetime scope");
        }

        Console.WriteLine("Disposed the root scope");

        Console.ReadLine();
    }
}

3 layanan, satu untuk setiap dukungan Autofac seumur hidup. Programnya sangat sederhana, kami memiliki cakupan seumur hidup root, cakupan seumur hidup luar, dan cakupan seumur hidup dalam.

Masing-masing cakupan seumur hidup ini menyelesaikan 2 instans dari setiap layanan, sehingga setiap layanan diselesaikan sebanyak 6 kali. Inilah hasilnya:

Created the root scope

    Just created TransientService #1
    Just created LifetimeScopeService #1
    Just created SingletonService #1
    Just created TransientService #2

        Created the outer lifetime scope

            Just created TransientService #3
            Just created LifetimeScopeService #2
            Just created TransientService #4

                Created the inner lifetime scope

                    Just created TransientService #5
                    Just created LifetimeScopeService #3
                    Just created TransientService #6

                    Disposing TransientService #6
                    Disposing LifetimeScopeService #3
                    Disposing TransientService #5

                Disposed the inner lifetime scope

            Disposing TransientService #4
            Disposing LifetimeScopeService #2
            Disposing TransientService #3

        Disposed the outer lifetime scope

    Disposing TransientService #2
    Disposing SingletonService #1
    Disposing LifetimeScopeService #1
    Disposing TransientService #1

Disposed the root scope

Beberapa pengamatan, selalu ingat bahwa semua layanan telah diselesaikan 6 kali dengan 3 cakupan seumur hidup yang berbeda

  • Kami mendapatkan 6 instance TransientService, yang cocok dengan registrasi yang kami buat pada container. Dari segi pembuangan, setiap cakupan seumur hidup membuang 2 contohnya saat dibuang.

  • Hanya 3 contoh LifetimeScopeService yang dibuat. Meskipun setiap cakupan seumur hidup menyelesaikan layanan ini dua kali, Autofac selalu mengembalikan, dalam cakupan seumur hidup yang sama, contoh yang sama pada kali kedua layanan tersebut diselesaikan. Setiap instance dibuang berdasarkan cakupan seumur hidup pemiliknya.

  • Hanya ada 1 contoh SingletonService di seluruh aplikasi. Tidak ada batasan cakupan seumur hidup di sini karena 3 cakupan seumur hidup diselesaikan ke instance layanan yang sama, yang dibuang ketika cakupan akar dibuang.

Edit: membuat indentasi keluaran agar lebih mudah dibaca dan membuat hierarki lebih jelas

person Mickaël Derriey    schedule 14.12.2016
comment
Maaf terlambat. Itu dijelaskan dengan baik dan contoh yang baik+1. sangat menghargai. Terima kasih banyak. - person Joe.wang; 16.07.2017
comment
@Mickael Derriey Pak apakah baik untuk menyatakan Transien seumur hidup jika kita memiliki permintaan 100000 - person Saineshwar; 21.08.2019
comment
Tidak yakin dengan maksud Anda, bisakah Anda menjelaskannya lebih lanjut? - person Mickaël Derriey; 21.08.2019
comment
Terima kasih. Saya perlu menguji asumsi saya tentang SingleInstance() saat mendaftar di cakupan anak dan ini menghemat banyak waktu. Jika Anda tidak keberatan, saya menaruhnya di GitHub: github.com /rhyous/Autofac.Examples/tree/master/src/ - person Rhyous; 17.12.2019