介绍
此系列文章主要是对ABP源码进行解读,初探作者在创造ABP的框架思路,和使用到的设计模式进行。
通过解读ABP源码,可以提升ABP使用方式,可以提升编码意识,提高面向对象编程思想。
在《ABP 源码解析 一. ABP启动》中介绍了ABP是如何启动的。
此篇文章主要解读ABP框架中IOC相关内容介绍。
ABP中的Ioc容器依赖Castle Windsor
。
在ABP启动中,可以看到是如何使用IOC的,在AbpBootstrapper
构造函数中,有如下代码
// 设置Ioc管理器
IocManager = options.IocManager;
由此可知,ABP容器是通过options
传递到启动类中的,通过阅读AbpBootstrapperOptions
类
public AbpBootstrapperOptions()
{
IocManager = Abp.Dependency.IocManager.Instance;
PlugInSources = new PlugInSourceList();
}
得知选项中的IocManager
是Abp.Dependency.IocManager.Instance
所得。
接下来我们主要依据IocManager.Instance
进行代码分析。
类文件结构图
IocManager IIocManager IIocRegistrar IIocResolver IConventionalRegistrationContext IConventionalDependencyRegistrar ConventionalRegistrationConfig DependencyLifeStyle源码解析
主要接口
abp和ioc有关的接口主要有三个
- IIocRegistrar:用于注册依赖项的类的接口
- IIocResolver:用于解析依赖的类的接口
- IIocManager:用于注册和解析依赖项的接口
1. IIocRegistrar
IIocRegistrar主要提供了各种注册依赖项的方法,以及提供是否已注册的检测方法
主要有:
- 普通注册:
AddConventionalRegistrar
- 程序集注册:
RegisterAssemblyByConvention
- 类型注册:
Register
- 检查是否已注册:
IsRegistered
/// <summary>
/// Define interface for classes those are used to register dependencies.
/// 定义用于注册依赖项的类的接口
/// </summary>
public interface IIocRegistrar
{
/// <summary>
/// Adds a dependency registrar for conventional registration.
/// 添加依赖注册器
/// </summary>
/// <param name="registrar">dependency registrar</param>
void AddConventionalRegistrar(IConventionalDependencyRegistrar registrar);
/// <summary>
/// Registers types of given assembly by all conventional registrars. See <see cref="IocManager.AddConventionalRegistrar"/> method.
/// 注册指定的信息集
/// </summary>
/// <param name="assembly">Assembly to register</param>
void RegisterAssemblyByConvention(Assembly assembly);
/// <summary>
/// Registers types of given assembly by all conventional registrars. See <see cref="IocManager.AddConventionalRegistrar"/> method.
/// 注册指定的信息集
/// </summary>
/// <param name="assembly">Assembly to register
/// 指定的信息集
/// </param>
/// <param name="config">Additional configuration
/// 配置
/// </param>
void RegisterAssemblyByConvention(Assembly assembly, ConventionalRegistrationConfig config);
/// <summary>
/// Registers a type as self registration.
/// 注册自身类型
/// </summary>
/// <typeparam name="T">Type of the class
/// 类的类型
/// </typeparam>
/// <param name="lifeStyle">Lifestyle of the objects of this type
/// 注册的生命周期
/// </param>
void Register<T>(DependencyLifeStyle lifeStyle = DependencyLifeStyle.Singleton)
where T : class;
/// <summary>
/// Registers a type as self registration.
/// 注册自身类型
/// </summary>
/// <param name="type">Type of the class
/// 类的类型
/// </param>
/// <param name="lifeStyle">Lifestyle of the objects of this type
/// 注册的生命周期
/// </param>
void Register(Type type, DependencyLifeStyle lifeStyle = DependencyLifeStyle.Singleton);
/// <summary>
/// Registers a type with it's implementation.
/// 注册一个类型的实现
/// </summary>
/// <typeparam name="TType">Registering type
/// 注册类型
/// </typeparam>
/// <typeparam name="TImpl">The type that implements <see cref="TType"/>
/// 实现类型
/// </typeparam>
/// <param name="lifeStyle">Lifestyle of the objects of this type
/// 注册的生命周期
/// </param>
void Register<TType, TImpl>(DependencyLifeStyle lifeStyle = DependencyLifeStyle.Singleton)
where TType : class
where TImpl : class, TType;
/// <summary>
/// Registers a type with it's implementation.
/// 注册一个类型的实现
/// </summary>
/// <param name="type">Type of the class
/// 注册类型
/// </param>
/// <param name="impl">The type that implements
/// 实现类型
/// <paramref name="type"/></param>
/// <param name="lifeStyle">Lifestyle of the objects of this type
/// 注册的生命周期
/// </param>
void Register(Type type, Type impl, DependencyLifeStyle lifeStyle = DependencyLifeStyle.Singleton);
/// <summary>
/// Checks whether given type is registered before.
/// 检查指定类型是否已注册
/// </summary>
/// <param name="type">Type to check
/// 指定类型
/// </param>
bool IsRegistered(Type type);
/// <summary>
/// Checks whether given type is registered before.
/// 检查指定类型是否已注册
/// </summary>
/// <typeparam name="TType">Type to check
/// 指定类型
/// </typeparam>
bool IsRegistered<TType>();
}
2. IIocResolver
IIocResolver
接口主要提供了如何从ioc容器中解析组件的方法,主要有
- 解析单个组件:
Resolve
- 解析全部组件:
ResolveAll
- 检查组件是否已注册:
IsRegistered
/// <summary>
/// Define interface for classes those are used to resolve dependencies.
/// 定义用于解析依赖的类的接口
/// </summary>
public interface IIocResolver
{
/// <summary>
/// Gets an object from IOC container.
/// Returning object must be Released (see <see cref="Release"/>) after usage.
/// 从IOC容器中获取一个对象
/// </summary>
/// <typeparam name="T">Type of the object to get
/// 获取类型
/// </typeparam>
/// <returns>The object instance
/// 对象实例
/// </returns>
T Resolve<T>();
/// <summary>
/// Gets an object from IOC container.
/// Returning object must be Released (see <see cref="Release"/>) after usage.
/// 从IOC容器中获取一个对象
/// </summary>
/// <typeparam name="T">Type of the object to cast
/// 对象转到的类型
/// </typeparam>
/// <param name="type">Type of the object to resolve
/// 解析的对象类型
/// </param>
/// <returns>The object instance
/// 对象实例
/// </returns>
T Resolve<T>(Type type);
/// <summary>
/// Gets an object from IOC container.
/// Returning object must be Released (see <see cref="Release"/>) after usage.
/// 从IOC容器中获取一个对象
/// </summary>
/// <typeparam name="T">Type of the object to get
/// 获取的对象类型
/// </typeparam>
/// <param name="argumentsAsAnonymousType">Constructor arguments
/// 构造函数参数
/// </param>
/// <returns>The object instance
/// 对象实例
/// </returns>
T Resolve<T>(object argumentsAsAnonymousType);
/// <summary>
/// Gets an object from IOC container.
/// Returning object must be Released (see <see cref="Release"/>) after usage.
/// 从IOC容器中获取一个对象
/// </summary>
/// <param name="type">Type of the object to get
/// 获取对象的类型
/// </param>
/// <returns>The object instance
/// 对象实例
/// </returns>
object Resolve(Type type);
/// <summary>
/// Gets an object from IOC container.
/// Returning object must be Released (see <see cref="Release"/>) after usage.
/// 从IOC容器中获取一个对象
/// </summary>
/// <param name="type">Type of the object to get
/// 获取对象的类型
/// </param>
/// <param name="argumentsAsAnonymousType">Constructor arguments
/// 构造函数参数
/// </param>
/// <returns>The object instance
/// 对象实例
/// </returns>
object Resolve(Type type, object argumentsAsAnonymousType);
/// <summary>
/// Gets all implementations for given type.
/// Returning objects must be Released (see <see cref="Release"/>) after usage.
/// 从IOC容器中获取全部对象
/// </summary>
/// <typeparam name="T">Type of the objects to resolve
/// 解析对象的类型
/// </typeparam>
/// <returns>Object instances
/// 全部对象实例
/// </returns>
T[] ResolveAll<T>();
/// <summary>
/// Gets all implementations for given type.
/// Returning objects must be Released (see <see cref="Release"/>) after usage.
/// 从IOC容器中获取全部对象
/// </summary>
/// <typeparam name="T">Type of the objects to resolve
/// 解析对象的类型
/// </typeparam>
/// <param name="argumentsAsAnonymousType">Constructor arguments
/// 构造函数参数
/// </param>
/// <returns>Object instances
/// 全部对象实例
/// </returns>
T[] ResolveAll<T>(object argumentsAsAnonymousType);
/// <summary>
/// Gets all implementations for given type.
/// Returning objects must be Released (see <see cref="Release"/>) after usage.
/// 从IOC容器中获取指定类型的全部对象
/// </summary>
/// <param name="type">Type of the objects to resolve
/// 解析对象的类型
/// </param>
/// <returns>Object instances
/// 全部对象实例
/// </returns>
object[] ResolveAll(Type type);
/// <summary>
/// Gets all implementations for given type.
/// Returning objects must be Released (see <see cref="Release"/>) after usage.
/// 从IOC容器中获取指定类型的全部对象
/// </summary>
/// <param name="type">Type of the objects to resolve
/// 解析对象的类型
/// </param>
/// <param name="argumentsAsAnonymousType">Constructor arguments
/// 构造函数参数
/// </param>
/// <returns>Object instances
/// 全部对象实例
/// </returns>
object[] ResolveAll(Type type, object argumentsAsAnonymousType);
/// <summary>
/// Releases a pre-resolved object. See Resolve methods.
/// 释放解析对象
/// </summary>
/// <param name="obj">Object to be released
/// 被释放的对象
/// </param>
void Release(object obj);
/// <summary>
/// Checks whether given type is registered before.
/// 检查给定类型是否已注册
/// </summary>
/// <param name="type">Type to check
/// 指定类型
/// </param>
bool IsRegistered(Type type);
/// <summary>
/// Checks whether given type is registered before.
/// 检查给定类型是否已注册
/// </summary>
/// <typeparam name="T">Type to check
/// 指定类型
/// </typeparam>
bool IsRegistered<T>();
}
3.IIocManager
IIocManager
继承自:IIocRegistrar,IIocResolver
,提供Ioc容器访问属性
/// <summary>
/// This interface is used to directly perform dependency injection tasks.
/// 用于注册和解析依赖项的接口
/// </summary>
public interface IIocManager : IIocRegistrar, IIocResolver, IDisposable
{
/// <summary>
/// Reference to the Castle Windsor Container.
/// Ioc容器
/// </summary>
IWindsorContainer IocContainer { get; }
/// <summary>
/// Checks whether given type is registered before.
/// 检查指定类型是否已经注入
/// </summary>
/// <param name="type">Type to check
/// 检查的类型
/// </param>
new bool IsRegistered(Type type);
/// <summary>
/// Checks whether given type is registered before.
/// 检查指定类型是否已经注入
/// </summary>
/// <typeparam name="T">Type to check
/// 检查的类型
/// </typeparam>
new bool IsRegistered<T>();
}
IocManager 实现
IocManager
是主要实现类,在此类中,初始化Windsor
容器,编译能够将类型注入到ioc容器中和从ioc容器中解析组件。
/// <summary>
/// This class is used to directly perform dependency injection tasks.
/// 负责依赖注入
/// </summary>
public class IocManager : IIocManager
{
/// <summary>
/// The Singleton instance.
/// IocManager单例
/// </summary>
public static IocManager Instance { get; private set; }
/// <summary>
/// Reference to the Castle Windsor Container.
/// Castle Windsor 容器
/// </summary>
public IWindsorContainer IocContainer { get; private set; }
/// <summary>
/// List of all registered conventional registrars.
/// </summary>
private readonly List<IConventionalDependencyRegistrar> _conventionalRegistrars;
static IocManager()
{
Instance = new IocManager();
}
/// <summary>
/// Creates a new <see cref="IocManager"/> object.
/// Normally, you don't directly instantiate an <see cref="IocManager"/>.
/// This may be useful for test purposes.
/// </summary>
public IocManager()
{
IocContainer = new WindsorContainer();
_conventionalRegistrars = new List<IConventionalDependencyRegistrar>();
//Register self!
IocContainer.Register(
Component.For<IocManager, IIocManager, IIocRegistrar, IIocResolver>().UsingFactoryMethod(() => this)
);
}
/// <summary>
/// Adds a dependency registrar for conventional registration.
/// </summary>
/// <param name="registrar">dependency registrar</param>
public void AddConventionalRegistrar(IConventionalDependencyRegistrar registrar)
{
_conventionalRegistrars.Add(registrar);
}
/// <summary>
/// Registers types of given assembly by all conventional registrars. See <see cref="AddConventionalRegistrar"/> method.
/// </summary>
/// <param name="assembly">Assembly to register</param>
public void RegisterAssemblyByConvention(Assembly assembly)
{
RegisterAssemblyByConvention(assembly, new ConventionalRegistrationConfig());
}
/// <summary>
/// Registers types of given assembly by all conventional registrars. See <see cref="AddConventionalRegistrar"/> method.
/// </summary>
/// <param name="assembly">Assembly to register</param>
/// <param name="config">Additional configuration</param>
public void RegisterAssemblyByConvention(Assembly assembly, ConventionalRegistrationConfig config)
{
var context = new ConventionalRegistrationContext(assembly, this, config);
foreach (var registerer in _conventionalRegistrars)
{
registerer.RegisterAssembly(context);
}
if (config.InstallInstallers)
{
IocContainer.Install(FromAssembly.Instance(assembly));
}
}
/// <summary>
/// Registers a type as self registration.
/// </summary>
/// <typeparam name="TType">Type of the class</typeparam>
/// <param name="lifeStyle">Lifestyle of the objects of this type</param>
public void Register<TType>(DependencyLifeStyle lifeStyle = DependencyLifeStyle.Singleton) where TType : class
{
IocContainer.Register(ApplyLifestyle(Component.For<TType>(), lifeStyle));
}
/// <summary>
/// Registers a type as self registration.
/// </summary>
/// <param name="type">Type of the class</param>
/// <param name="lifeStyle">Lifestyle of the objects of this type</param>
public void Register(Type type, DependencyLifeStyle lifeStyle = DependencyLifeStyle.Singleton)
{
IocContainer.Register(ApplyLifestyle(Component.For(type), lifeStyle));
}
/// <summary>
/// Registers a type with it's implementation.
/// </summary>
/// <typeparam name="TType">Registering type</typeparam>
/// <typeparam name="TImpl">The type that implements <see cref="TType"/></typeparam>
/// <param name="lifeStyle">Lifestyle of the objects of this type</param>
public void Register<TType, TImpl>(DependencyLifeStyle lifeStyle = DependencyLifeStyle.Singleton)
where TType : class
where TImpl : class, TType
{
IocContainer.Register(ApplyLifestyle(Component.For<TType, TImpl>().ImplementedBy<TImpl>(), lifeStyle));
}
/// <summary>
/// Registers a type with it's implementation.
/// </summary>
/// <param name="type">Type of the class</param>
/// <param name="impl">The type that implements <paramref name="type"/></param>
/// <param name="lifeStyle">Lifestyle of the objects of this type</param>
public void Register(Type type, Type impl, DependencyLifeStyle lifeStyle = DependencyLifeStyle.Singleton)
{
IocContainer.Register(ApplyLifestyle(Component.For(type, impl).ImplementedBy(impl), lifeStyle));
}
/// <summary>
/// Checks whether given type is registered before.
/// </summary>
/// <param name="type">Type to check</param>
public bool IsRegistered(Type type)
{
return IocContainer.Kernel.HasComponent(type);
}
/// <summary>
/// Checks whether given type is registered before.
/// </summary>
/// <typeparam name="TType">Type to check</typeparam>
public bool IsRegistered<TType>()
{
return IocContainer.Kernel.HasComponent(typeof(TType));
}
/// <summary>
/// Gets an object from IOC container.
/// Returning object must be Released (see <see cref="IIocResolver.Release"/>) after usage.
/// </summary>
/// <typeparam name="T">Type of the object to get</typeparam>
/// <returns>The instance object</returns>
public T Resolve<T>()
{
return IocContainer.Resolve<T>();
}
/// <summary>
/// Gets an object from IOC container.
/// Returning object must be Released (see <see cref="Release"/>) after usage.
/// </summary>
/// <typeparam name="T">Type of the object to cast</typeparam>
/// <param name="type">Type of the object to resolve</param>
/// <returns>The object instance</returns>
public T Resolve<T>(Type type)
{
return (T)IocContainer.Resolve(type);
}
/// <summary>
/// Gets an object from IOC container.
/// Returning object must be Released (see <see cref="IIocResolver.Release"/>) after usage.
/// </summary>
/// <typeparam name="T">Type of the object to get</typeparam>
/// <param name="argumentsAsAnonymousType">Constructor arguments</param>
/// <returns>The instance object</returns>
public T Resolve<T>(object argumentsAsAnonymousType)
{
return IocContainer.Resolve<T>(argumentsAsAnonymousType);
}
/// <summary>
/// Gets an object from IOC container.
/// Returning object must be Released (see <see cref="IIocResolver.Release"/>) after usage.
/// </summary>
/// <param name="type">Type of the object to get</param>
/// <returns>The instance object</returns>
public object Resolve(Type type)
{
return IocContainer.Resolve(type);
}
/// <summary>
/// Gets an object from IOC container.
/// Returning object must be Released (see <see cref="IIocResolver.Release"/>) after usage.
/// </summary>
/// <param name="type">Type of the object to get</param>
/// <param name="argumentsAsAnonymousType">Constructor arguments</param>
/// <returns>The instance object</returns>
public object Resolve(Type type, object argumentsAsAnonymousType)
{
return IocContainer.Resolve(type, argumentsAsAnonymousType);
}
///<inheritdoc/>
public T[] ResolveAll<T>()
{
return IocContainer.ResolveAll<T>();
}
///<inheritdoc/>
public T[] ResolveAll<T>(object argumentsAsAnonymousType)
{
return IocContainer.ResolveAll<T>(argumentsAsAnonymousType);
}
///<inheritdoc/>
public object[] ResolveAll(Type type)
{
return IocContainer.ResolveAll(type).Cast<object>().ToArray();
}
///<inheritdoc/>
public object[] ResolveAll(Type type, object argumentsAsAnonymousType)
{
return IocContainer.ResolveAll(type, argumentsAsAnonymousType).Cast<object>().ToArray();
}
/// <summary>
/// Releases a pre-resolved object. See Resolve methods.
/// </summary>
/// <param name="obj">Object to be released</param>
public void Release(object obj)
{
IocContainer.Release(obj);
}
/// <inheritdoc/>
public void Dispose()
{
IocContainer.Dispose();
}
private static ComponentRegistration<T> ApplyLifestyle<T>(ComponentRegistration<T> registration, DependencyLifeStyle lifeStyle)
where T : class
{
switch (lifeStyle)
{
case DependencyLifeStyle.Transient:
return registration.LifestyleTransient();
case DependencyLifeStyle.Singleton:
return registration.LifestyleSingleton();
default:
return registration;
}
}
}
1. 初始化容器
在IocManager 构造函数,初始化了 WindsorContainer
容器,并且将自身实例,注入到容器中,以便能解析IocManager, IIocManager, IIocRegistrar, IIocResolver
组件
public IocManager()
{
IocContainer = new WindsorContainer();
_conventionalRegistrars = new List<IConventionalDependencyRegistrar>();
//Register self!
IocContainer.Register(
Component.For<IocManager, IIocManager, IIocRegistrar, IIocResolver>().UsingFactoryMethod(() => this)
);
}
2. 注册组件
由于已经初始化了WindsorContainer
容器,abp抽象了集中常用的注册方式,直接注入到容器中
public void RegisterAssemblyByConvention(Assembly assembly, ConventionalRegistrationConfig config)
{
var context = new ConventionalRegistrationContext(assembly, this, config);
foreach (var registerer in _conventionalRegistrars)
{
registerer.RegisterAssembly(context);
}
if (config.InstallInstallers)
{
IocContainer.Install(FromAssembly.Instance(assembly));
}
}
public void Register<TType>(DependencyLifeStyle lifeStyle = DependencyLifeStyle.Singleton) where TType : class
{
IocContainer.Register(ApplyLifestyle(Component.For<TType>(), lifeStyle));
}
3. 解析组件
抽象方法,从WindsorContainer
中解析
/// <summary>
/// Gets an object from IOC container.
/// Returning object must be Released (see <see cref="IIocResolver.Release"/>) after usage.
/// </summary>
/// <typeparam name="T">Type of the object to get</typeparam>
/// <returns>The instance object</returns>
public T Resolve<T>()
{
return IocContainer.Resolve<T>();
}
///<inheritdoc/>
public T[] ResolveAll<T>()
{
return IocContainer.ResolveAll<T>();
}
4. 检查是否已注册
检测组件是否已在WindsorContainer
中注册
/// <summary>
/// Checks whether given type is registered before.
/// </summary>
/// <param name="type">Type to check</param>
public bool IsRegistered(Type type)
{
return IocContainer.Kernel.HasComponent(type);
}
/// <summary>
/// Checks whether given type is registered before.
/// </summary>
/// <typeparam name="TType">Type to check</typeparam>
public bool IsRegistered<TType>()
{
return IocContainer.Kernel.HasComponent(typeof(TType));
}
设计模式
1. 单例模式
IocManager
提供的单例模式,严格意义上,IocManager
类还不算是单例,因为其构造方法是public
,也就意味着,可以直接创建IocManager
实例。
/// <summary>
/// The Singleton instance.
/// IocManager单例
/// </summary>
public static IocManager Instance { get; private set; }
static IocManager()
{
Instance = new IocManager();
}
public IocManager()
{
}
2. 代理模式
IocManager
也使用到了代理模式,抽象封装自己的接口信息,代理IWindsorContainer
,丰富框架内的接口。
测试代码
和ioc容器有关的测试,如下图
ioc测试
public class IocManager_LifeStyle_Tests : TestBaseWithLocalIocManager
{
/// <summary>
/// 当组件释放时需要调用Dispose
/// </summary>
[Fact]
public void Should_Call_Dispose_Of_Transient_Dependency_When_Object_Is_Released()
{
LocalIocManager.IocContainer.Register(
Component.For<SimpleDisposableObject>().LifestyleTransient()
);
var obj = LocalIocManager.IocContainer.Resolve<SimpleDisposableObject>();
LocalIocManager.IocContainer.Release(obj);
obj.DisposeCount.ShouldBe(1);
}
/// <summary>
/// 当iocManager 释放之后,对象也被释放
/// </summary>
[Fact]
public void Should_Call_Dispose_Of_Transient_Dependency_When_IocManager_Is_Disposed()
{
LocalIocManager.IocContainer.Register(
Component.For<SimpleDisposableObject>().LifestyleTransient()
);
var obj = LocalIocManager.IocContainer.Resolve<SimpleDisposableObject>();
LocalIocManager.Dispose();
obj.DisposeCount.ShouldBe(1);
}
/// <summary>
/// 当iocManager 释放之后,单例对象也被释放
/// </summary>
[Fact]
public void Should_Call_Dispose_Of_Singleton_Dependency_When_IocManager_Is_Disposed()
{
LocalIocManager.IocContainer.Register(
Component.For<SimpleDisposableObject>().LifestyleSingleton()
);
var obj = LocalIocManager.IocContainer.Resolve<SimpleDisposableObject>();
LocalIocManager.Dispose();
obj.DisposeCount.ShouldBe(1);
}
}
public class ScopedIocResolver_Tests : TestBaseWithLocalIocManager
{
/// <summary>
/// scope需要正常运行
/// </summary>
[Fact]
public void UsingScope_Test_ShouldWork()
{
LocalIocManager.Register<SimpleDisposableObject>(DependencyLifeStyle.Transient);
SimpleDisposableObject simpleObj = null;
LocalIocManager.UsingScope(scope => { simpleObj = scope.Resolve<SimpleDisposableObject>(); });
simpleObj.DisposeCount.ShouldBe(1);
}
/// <summary>
/// 带有构造函数的scope能够正常运行
/// </summary>
[Fact]
public void UsingScope_Test_With_Constructor_ShouldWork()
{
LocalIocManager.Register<SimpleDisposableObject>(DependencyLifeStyle.Transient);
SimpleDisposableObject simpleObj = null;
LocalIocManager.UsingScope(scope => { simpleObj = scope.Resolve<SimpleDisposableObject>(new { myData = 40 }); });
simpleObj.MyData.ShouldBe(40);
}
/// <summary>
/// IIocScopedResolver接口正常
/// </summary>
[Fact]
public void IIocScopedResolver_Test_ShouldWork()
{
LocalIocManager.Register<SimpleDisposableObject>(DependencyLifeStyle.Transient);
LocalIocManager.Register<SimpleDisposableObject2>(DependencyLifeStyle.Transient);
LocalIocManager.Register<SimpleDisposableObject3>(DependencyLifeStyle.Transient);
SimpleDisposableObject simpleObj;
SimpleDisposableObject2 simpleObj2;
SimpleDisposableObject3 simpleObj3;
using (var scope = LocalIocManager.CreateScope())
{
simpleObj = scope.Resolve<SimpleDisposableObject>();
simpleObj2 = scope.Resolve<SimpleDisposableObject2>();
simpleObj3 = scope.Resolve<SimpleDisposableObject3>();
}
simpleObj.DisposeCount.ShouldBe(1);
simpleObj2.DisposeCount.ShouldBe(1);
simpleObj3.DisposeCount.ShouldBe(1);
}
/// <summary>
/// IIocScopedResolver接口正常,解析组件有构造函数
/// </summary>
[Fact]
public void IIocScopedResolver_Test_With_ConstructorArgs_ShouldWork()
{
LocalIocManager.Register<SimpleDisposableObject>(DependencyLifeStyle.Transient);
LocalIocManager.Register<SimpleDisposableObject2>(DependencyLifeStyle.Transient);
LocalIocManager.Register<SimpleDisposableObject3>(DependencyLifeStyle.Transient);
SimpleDisposableObject simpleObj;
SimpleDisposableObject2 simpleObj2;
SimpleDisposableObject3 simpleObj3;
using (var scope = LocalIocManager.CreateScope())
{
simpleObj = scope.Resolve<SimpleDisposableObject>(new { myData = 40 });
simpleObj2 = scope.Resolve<SimpleDisposableObject2>(new { myData = 4040 });
simpleObj3 = scope.Resolve<SimpleDisposableObject3>(new { myData = 404040 });
}
simpleObj.MyData.ShouldBe(40);
simpleObj2.MyData.ShouldBe(4040);
simpleObj3.MyData.ShouldBe(404040);
}
[Fact]
public void IIocScopedResolver_Test_ResolveAll_Should_DisposeAll_Registrants()
{
LocalIocManager.Register<ISimpleDependency, SimpleDependency>(DependencyLifeStyle.Transient);
LocalIocManager.Register<ISimpleDependency, SimpleDependency2>(DependencyLifeStyle.Transient);
LocalIocManager.Register<ISimpleDependency, SimpleDependency3>(DependencyLifeStyle.Transient);
IEnumerable<ISimpleDependency> simpleDependendcies;
using (var scope = LocalIocManager.CreateScope())
{
simpleDependendcies = scope.ResolveAll<ISimpleDependency>();
}
simpleDependendcies.ShouldAllBe(d => d.DisposeCount == 1);
}
[Fact]
public void IIocScopedResolver_Test_ResolveAll_Should_Work_WithConstructor()
{
LocalIocManager.Register<ISimpleDependency, SimpleDependency>(DependencyLifeStyle.Transient);
LocalIocManager.Register<ISimpleDependency, SimpleDependency2>(DependencyLifeStyle.Transient);
LocalIocManager.Register<ISimpleDependency, SimpleDependency3>(DependencyLifeStyle.Transient);
IEnumerable<ISimpleDependency> simpleDependendcies;
using (var scope = LocalIocManager.CreateScope())
{
simpleDependendcies = scope.ResolveAll<ISimpleDependency>(new { myData = 40 });
}
simpleDependendcies.ShouldAllBe(x => x.MyData == 40);
}
[Fact]
public void IIocScopedResolver_Test_ResolveAll_Should_Work_With_OtherResolvings()
{
LocalIocManager.Register<ISimpleDependency, SimpleDependency>(DependencyLifeStyle.Transient);
LocalIocManager.Register<ISimpleDependency, SimpleDependency2>(DependencyLifeStyle.Transient);
LocalIocManager.Register<ISimpleDependency, SimpleDependency3>(DependencyLifeStyle.Transient);
LocalIocManager.Register<SimpleDisposableObject>(DependencyLifeStyle.Transient);
IEnumerable<ISimpleDependency> simpleDependendcies;
SimpleDisposableObject simpleObject;
using (var scope = LocalIocManager.CreateScope())
{
simpleDependendcies = scope.ResolveAll<ISimpleDependency>();
simpleObject = scope.Resolve<SimpleDisposableObject>();
}
simpleDependendcies.ShouldAllBe(x => x.DisposeCount == 1);
simpleObject.DisposeCount.ShouldBe(1);
}
[Fact]
public void IIocScopedResolver_Test_ResolveAll_Should_Work_With_OtherResolvings_ConstructorArguments()
{
LocalIocManager.Register<ISimpleDependency, SimpleDependency>(DependencyLifeStyle.Transient);
LocalIocManager.Register<ISimpleDependency, SimpleDependency2>(DependencyLifeStyle.Transient);
LocalIocManager.Register<ISimpleDependency, SimpleDependency3>(DependencyLifeStyle.Transient);
LocalIocManager.Register<SimpleDisposableObject>(DependencyLifeStyle.Transient);
IEnumerable<ISimpleDependency> simpleDependendcies;
SimpleDisposableObject simpleObject;
using (var scope = LocalIocManager.CreateScope())
{
simpleDependendcies = scope.ResolveAll<ISimpleDependency>(new { myData = 40 });
simpleObject = scope.Resolve<SimpleDisposableObject>(new { myData = 40 });
}
simpleDependendcies.ShouldAllBe(x => x.MyData == 40);
simpleObject.MyData.ShouldBe(40);
}
[Fact]
public void IIocScopedResolver_Test_IsRegistered_ShouldWork()
{
LocalIocManager.Register<ISimpleDependency, SimpleDependency>(DependencyLifeStyle.Transient);
using (var scope = LocalIocManager.CreateScope())
{
scope.IsRegistered<ISimpleDependency>().ShouldBe(true);
scope.IsRegistered(typeof(ISimpleDependency)).ShouldBe(true);
}
}
[Fact]
public void IIocScopedResolver_Test_Custom_Release_ShouldWork()
{
LocalIocManager.Register<ISimpleDependency, SimpleDependency>(DependencyLifeStyle.Transient);
ISimpleDependency simpleDependency;
using (var scope = LocalIocManager.CreateScope())
{
simpleDependency = scope.Resolve<ISimpleDependency>();
scope.Release(simpleDependency);
}
simpleDependency.DisposeCount.ShouldBe(1);
}
}
public interface ISimpleDependency : IDisposable
{
int MyData { get; set; }
int DisposeCount { get; set; }
}
public class SimpleDependency : ISimpleDependency
{
public int MyData { get; set; }
public int DisposeCount { get; set; }
public void Dispose()
{
DisposeCount++;
}
}
public class SimpleDependency2 : ISimpleDependency
{
public int DisposeCount { get; set; }
public int MyData { get; set; }
public void Dispose()
{
DisposeCount++;
}
}
public class SimpleDependency3 : ISimpleDependency
{
public int MyData { get; set; }
public int DisposeCount { get; set; }
public void Dispose()
{
DisposeCount++;
}
}
运行测试结果
我的公众号
网友评论