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