很多 Ioc 框架在创建对象的过程中,都会采取某种方式来缓存/复用/释放已构建的对象。在 My.Ioc 中,这个目的是通过 Lifetime/ILifetimeScope 来实现的。其中,Lifetime 实现了缓存/复用对象的功能,ILifetimeScope 则实现了复用/释放对象的功能。

My.Ioc 默认提供了三种 Lifetime:ContainerLifetime、TransientLifetime 和 ScopeLifetime。这里简单解释一下它们的含义:ContainerLifetime 继承自 SingletonLifetime,它实际上是一种单例模式的实现。TransientLifetime 顾名思义,即每次请求都新建一个对象返回给调用者。ScopeLifetime 则表明在某个 scope 及其父 scope 中创建的对象将在该 scope 内复用。

上面这样解释也许大家不是很容易明白,下面我们结合示例代码来说明:

using System;
using System.Diagnostics;
using My.Ioc;
using My.Ioc.Exceptions;

namespace LifetimeAndLifetimeScope
{
    #region Test Types

    public class SingletonDisposableClass : IDisposable
    {
        public void Dispose()
        {
            Console.WriteLine("Disposing SingletonDisposableClass...");
        }
    }
    public class SingletonNonDisposableClass { }

    public class TransientNonDisposableClass { }
    public class TransientDisposableClass : IDisposable 
    { 
        public void Dispose()
        {
            Console.WriteLine("Disposing TransientDisposableClass...");
        }
    }

    public class ScopedDisposableClass : IDisposable
    {
        public void Dispose()
        {
            Console.WriteLine("Disposing ScopedDisposableClass...");
        }
    }
    public class ScopedNonDisposableClass
    {
    }

    #endregion

    class Program
    {
        static void Main(string[] args)
        {
            var container = new ObjectContainer(false);
            Register(container);
            
            ResolveTransient(container);
            ResolveScope(container);
            ResolveSingleton(container);
            
            // Dispose the container
            // The disposable singleton instances should be disposed here.
            container.Dispose();
            Console.ReadLine();
        }

        static void Register(IObjectContainer container)
        {
            container.Register<TransientDisposableClass>()
                .In(Lifetime.Transient()); // This line can be omitted
            container.Register<TransientNonDisposableClass>()
                .In(Lifetime.Transient()); // This line can be omitted

            container.Register<ScopedDisposableClass>()
                .In(Lifetime.Scope());
            container.Register<ScopedNonDisposableClass>()
                .In(Lifetime.Scope());
            
            container.Register<SingletonDisposableClass>()
                .In(Lifetime.Container()); //Singleton
            container.Register<SingletonNonDisposableClass>()
                .In(Lifetime.Container()); //Singleton
            
            container.CommitRegistrations();
        }

        static void ResolveTransient(IObjectContainer container)
        {
            var nonDisposable1 = container.Resolve<TransientNonDisposableClass>();
            var nonDisposable2 = container.Resolve<TransientNonDisposableClass>();
            Debug.Assert(nonDisposable1 != nonDisposable2, "nonDisposable1 == nonDisposable2");

            try
            {
                var disposable_Error = container.Resolve<TransientDisposableClass>();
            }
            catch (Exception ex)
            {
                Debug.Assert(ex is InvalidLifetimeScopeException);
            }

            using (var scope = container.BeginLifetimeScope())
            {
                var disposable1 = container.Resolve<TransientDisposableClass>();
                var disposable2 = container.Resolve<TransientDisposableClass>();
                Debug.Assert(disposable1 != disposable2, "disposable1 == disposable2");
            }
        }

        static void ResolveScope(IObjectContainer container)
        {
            try
            {
                var nondisposable_Error = container.Resolve<ScopedNonDisposableClass>();
            }
            catch (Exception ex)
            {
                Debug.Assert(ex is InvalidLifetimeScopeException);
            }

            string nested_scope_should_share_instance =
                "{0} should be the same to {1}, because the {0} is resolved in the outer scope, "
                + "which is shared with the scope where {1} is resolved, so they must be a same instance.";

            string same_scope_should_share_instance =
                "{0} should be the same to {1}, because they are resolved in the same scope.";
           
            using (var scope1 = container.BeginLifetimeScope())
            {
                var disposable1 = scope1.Resolve<ScopedDisposableClass>();
                var nonDisposable1 = scope1.Resolve<ScopedNonDisposableClass>();
                
                using (var scope2 = scope1.BeginLifetimeScope())
                {
                    var disposable2 = scope2.Resolve<ScopedDisposableClass>();
                    var disposable3 = scope2.Resolve<ScopedDisposableClass>();
                    Debug.Assert(disposable1 == disposable2,
                        string.Format(nested_scope_should_share_instance, "disposable1", "disposable2"));
                    Debug.Assert(disposable1 == disposable3,
                        string.Format(nested_scope_should_share_instance, "disposable1", "disposable3"));
                    Debug.Assert(disposable2 == disposable3,
                        string.Format(same_scope_should_share_instance, "disposable2", "disposable3"));
                    
                    var nonDisposable2 = scope1.Resolve<ScopedNonDisposableClass>();
                    var nonDisposable3 = scope1.Resolve<ScopedNonDisposableClass>();
                    Debug.Assert(nonDisposable1 == nonDisposable2,
                        string.Format(nested_scope_should_share_instance, "nonDisposable1", "nonDisposable2"));
                    Debug.Assert(nonDisposable1 == nonDisposable3,
                        string.Format(nested_scope_should_share_instance, "nonDisposable1", "nonDisposable3"));
                    Debug.Assert(nonDisposable2 == nonDisposable3,
                        string.Format(same_scope_should_share_instance, "nonDisposable2", "nonDisposable3"));
                }
            }
        }
        
        static void ResolveSingleton(IObjectContainer container)
        {
            var disposable1 = container.Resolve<SingletonDisposableClass>();
            var disposable2 = container.Resolve<SingletonDisposableClass>();
            Debug.Assert(disposable1 == disposable2, "disposable1 != disposable2");
            
            var nonDisposable1 = container.Resolve<SingletonDisposableClass>();
            var nonDisposable2 = container.Resolve<SingletonDisposableClass>();
            Debug.Assert(nonDisposable1 == nonDisposable2, "disposable1 != nonDisposable2");
        }
    }
}
View Code

相关文章:

  • 2022-01-19
  • 2021-11-30
  • 2022-02-11
  • 2022-03-05
  • 2021-10-15
  • 2021-06-19
  • 2021-11-13
  • 2022-01-10
猜你喜欢
  • 2021-07-15
  • 2021-09-04
  • 2021-06-17
  • 2022-12-23
  • 2022-01-15
  • 2021-04-25
  • 2021-07-15
相关资源
相似解决方案