标签:style blog http color io os 使用 ar strong
很多 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"); } } }
在示例中,我们设计了这么三对类型:SingletonDisposableClass/SingletonNonDisposableClass、ScopedDisposableClass/ScopedNonDisposableClass 以及 TransientNonDisposableClass/TransientDisposableClass。用意很简单,分别注册到上面三种类型的 Lifetime 中。而每一类对象之所以有 Disposable 和 NonDisposable 两个类型,是因为我们要展示这三类 Lifetime 中对象清理的策略。
我们首先在 Register 方法中将 SingletonDisposableClass/SingletonNonDisposableClass 注册为 Container 生命周期,将 ScopedDisposableClass/ScopedNonDisposableClass 注册为 Scope 生命周期,并将 TransientNonDisposableClass/TransientDisposableClass 注册为 Transient 生命周期。
做好了准备工作之后,下面我们要让容器来为我们创建上述对象。首先,我们看 ResolveTransient 这个方法。这个方法旨在告诉我们:
接着,我们来看一下 ResolveScope 这个方法。这个方法是我们用来演示 ScopeLifetime 的运行方式的。它告诉我们:
最后我们来看 ResolveSingleton 这个方法。我们使用这个方法来观察 ContainerLifetime 的运行方式。这个方法的运行结果告诉我们:
本文源码可在此处下载,压缩包中包含了 My.Ioc 框架的源码和本示例以及其他一些示例的源码。
My.Ioc 代码示例——Lifetime 和 ILifetimeScope
标签:style blog http color io os 使用 ar strong
原文地址:http://www.cnblogs.com/johnny-liu/p/3962834.html