现在的编程思想,离不开IOC依赖注入,手写实现一个简易IOC容器,更深入理解依赖注入
还没了解IOC的可以查阅.net IOC框架 Unity&Autofac
本文章主要实现
- IOC容器基础注册
- 进阶完善别名以及构造函数注入
- 对象的生命周期管理
一、IoC容器实现
测试接口类
public interface ILanguage
{
public string GetContent();
}
测试接口实现类
public class Chinese : ILanguage
{
public string GetContent()
{
return "学习中文";
}
}
public class English : ILanguage
{
public string GetContent()
{
return "Learning English";
}
}
自定义容器接口类
public interface IMyContainer
{
///
/// 注册单一类型
///
///
void RegisterType();
///
/// 注册单一类型
///
///
/// 别名
void RegisterType(string name);
///
/// 映射关系
///
///
///
void RegisterType();
///
/// 映射关系
///
///
///
/// 别名
void RegisterType(string name);
///
/// 解析类型
///
///
///
TType Resolve();
///
/// 解析类型
///
///
/// 别名
///
TType Resolve(string name);
容器接口实现类
public class MyContainer : IMyContainer
{
//键用来映射关系,使用字典作为登记本
private static readonly Dictionary ContainerDictionary = new Dictionary();
public void RegisterType()
=> RegisterType(null);
public void RegisterType()
=> RegisterType(null);
public void RegisterType(string name)=>
RegisterType(null);
public void RegisterType(string name)
{
string key = typeof(TType).FullName;
if (!string.IsNullOrEmpty(name)) key = name;
if (ContainerDictionary.ContainsKey(key))
ContainerDictionary[key] = typeof(TImplementation); //如果存在采取覆盖形式
else
ContainerDictionary.Add(key, typeof(TImplementation));//将传进来的泛型Type进行关系映射
}
public TType Resolve() =>
Resolve(null);
public TType Resolve(string name)
{
//解析泛型Type获取key
var key = typeof(TType).FullName;
if (!string.IsNullOrEmpty(name)) key = name;
// 根据key从容器中获取实现类
var type = (Type)ContainerDictionary[key];
//创建对象
return (TType)Activator.CreateInstance(type);
}
}
main函数依赖注入测试
static void Main(string[] args)
{
var container = new MyContainer();
container.RegisterType();
//使用别名注册
container.RegisterType("english");
var language = container.Resolve();
var english = container.Resolve("english");
Console.WriteLine(language.GetContent());
Console.WriteLine(english.GetContent());
Console.Read();
}
输出结果
二、构造函数注入
创建特性类标记构造函数
public class MyinjectionAttribute : Attribute
{
}
使用自定义创建实例类进行对象实例化
1.优先使用被特性标记的构造函数
2.没有特性标记选择参数最多的构造函数,参数个数一致,按默认顺序选择第一个
//多个构造函数选择构造函数来创建实例
//1.优先使用被特性标记的构造函数
//2.没有特性标记选择参数最多的构造函数,参数个数一致,按默认顺序选择第一个
///
/// 创建实例
///
///
///
private object CreateInstance(Type type)
{
//获取所有的构造函数
var ctors = type.GetConstructors();
//获取被标记的构造函数
var ctor = ctors.FirstOrDefault(t => t.IsDefined(typeof(MyinjectionAttribute), true));
if (ctor != null) CreateInstance(type, ctor);
//没有特性获取参数最多的一个
ctor = ctors.OrderByDescending(t => t.GetParameters().Length).First();
return CreateInstance(type, ctor);
}
///
/// 构造函数注入
///
///
///
///
private object CreateInstance(Type type, ConstructorInfo ctor)
{
//获取构造函数参数
var paraArray = ctor.GetParameters();
if (paraArray.Length == 0)
{
return Activator.CreateInstance(type);
}
var parameters = new List
修改Resolve函数调用自身创建对象函数CreateInstance
public TType Resolve(string name)
{
//解析泛型Type获取key
var key = typeof(TType).FullName;
if (!string.IsNullOrEmpty(name)) key = name;
// 根据key从容器中获取实现类
var type = (Type)ContainerDictionary[key];
//创建对象
return (TType)CreateInstance(type);
}
新建Learn类进行测试
public class Learn
{
private ILanguage Language { get; set; }
//标记特性
[Myinjection]
public Learn(ILanguage language)
{
Language = language;
}
public void Read()
{
Console.WriteLine(Language.GetContent());
}
}
main函数
static void Main(string[] args)
{
var container = new MyContainer();
container.RegisterType();
//注入learn
container.RegisterType();
var learn = container.Resolve();
learn.Read();
Console.Read();
}
测试结果:
三、生命周期管理
这里实现三种常用生命周期模式:单例,瞬时,线程单例(作用域)
定义生命周期管理接口类,便于扩展
public interface ILifeTimeManager
{
object CreateInstance(Type type, params object[] args);
}
单例模式实现类
public class SingletonLifeTimeManager : ILifeTimeManager
{
//单例字典
private readonly Dictionary _singletonDictionary = new Dictionary();
public object CreateInstance(Type type, params object[] args)
{
var key = type.FullName;
if (_singletonDictionary.ContainsKey(key)) return _singletonDictionary[key];
var instance = Activator.CreateInstance(type, args);
_singletonDictionary.Add(key, instance);
return instance;
}
}
瞬时模式实现类
public class TransientLifeTimeManger : ILifeTimeManager
{
public object CreateInstance(Type type, params object[] args)
{
return Activator.CreateInstance(type, args);
}
}
线程单例实现类
public class PerThreadLifeTimeManager : ILifeTimeManager
{
//通过线程本地存储进行线程单例管理
private readonly ThreadLocal> _perThreadDictonary =
new ThreadLocal>();
public object CreateInstance(Type type, params object[] args)
{
//判断线程存储是否存在字段对象
if (_perThreadDictonary.Value == null)
_perThreadDictonary.Value = new Dictionary();
var key = type.FullName;
if (_perThreadDictonary.Value.ContainsKey(key)) return _perThreadDictonary.Value[key];
var instance = Activator.CreateInstance(type, args);
_perThreadDictonary.Value.Add(key, instance);
return instance;
}
}
定义生命周期类型静态类(用于管理生命周期类型)
public static class TypeLifeTime
{
public static ILifeTimeManager Singleton = new SingletonLifeTimeManager();
public static ILifeTimeManager Transient = new TransientLifeTimeManger();
public static ILifeTimeManager PerThread = new PerThreadLifeTimeManager();
}
定义保存注册映射信息实体类,以及扩展方法类
public class RegisteredType
{
public Type TargetType { get; set; }
public ILifeTimeManager LifeTimeManager { get; set; }
}
public static class RegisteredTypeExtension
{
public static object CreateInstance(this RegisteredType type, params object[] args)
{
//使用生命周期管理创建实例
return type.LifeTimeManager.CreateInstance(type.TargetType, args);
}
}
IMyContainer 接口类新增生命周期管理接口
///
/// 注册单一类型
///
///
/// 生命周期管理
void RegisterType(ILifeTimeManager lifeTimeManager);
///
/// 注册单一类型
///
///
/// 别名
/// 生命周期管理
void RegisterType(string name, ILifeTimeManager lifeTimeManager);
///
/// 映射关系
///
///
///
/// 生命周期管理
void RegisterType(ILifeTimeManager lifeTimeManager);
///
/// 映射关系
///
///
///
/// 别名
/// 生命周期管理
void RegisterType(string name, ILifeTimeManager lifeTimeManager);
MyContainer 接口实现类修改如下
public class MyContainer : IMyContainer
{
//键用来映射关系,使用字典作为登记本
private static readonly Dictionary ContainerDictionary = new Dictionary();
public void RegisterType()
=> RegisterType("");
public void RegisterType()
=> RegisterType("");
public void RegisterType(string name) =>
RegisterType("");
public void RegisterType(string name)=>
RegisterType(name, TypeLifeTime.Transient);
public void RegisterType(ILifeTimeManager lifeTimeManager)=>
RegisterType(lifeTimeManager);
public void RegisterType(ILifeTimeManager lifeTimeManager)=>
RegisterType("", lifeTimeManager);
public void RegisterType(string name, ILifeTimeManager lifeTimeManager) =>
RegisterType(name, lifeTimeManager);
public void RegisterType(string name, ILifeTimeManager lifeTimeManager)
{
string key = typeof(TType).FullName;
if (!string.IsNullOrEmpty(name)) key = name;
if (ContainerDictionary.ContainsKey(key)) //如果存在覆盖
ContainerDictionary[key] = new RegisteredType
{
TargetType = typeof(TImplementation),
LifeTimeManager = lifeTimeManager
};
else
ContainerDictionary.Add(key, new RegisteredType
{
TargetType = typeof(TImplementation),
LifeTimeManager = lifeTimeManager
});//将传进来的泛型Type进行关系映射
}
public TType Resolve() =>
Resolve("");
public TType Resolve(string name)
{
//解析泛型Type获取key
var key = typeof(TType).FullName;
if (!string.IsNullOrEmpty(name)) key = name;
// 根据key从容器中获取实现类
var type = ContainerDictionary[key];
//创建对象
return (TType)CreateInstance(type);
}
//多个构造函数选择构造函数来创建实例
//1.优先使用被特性标记的构造函数
//2.没有特性标记选择参数最多的构造函数,参数个数一致,按默认顺序选择第一个
///
/// 创建实例
///
///
///
private object CreateInstance(RegisteredType type)
{
//获取所有的构造函数
var ctors = type.TargetType.GetConstructors();
//获取被标记的构造函数
var ctor = ctors.FirstOrDefault(t => t.IsDefined(typeof(MyinjectionAttribute), true));
if (ctor != null) CreateInstance(type, ctor);
//没有特性获取参数最多的一个
ctor = ctors.OrderByDescending(t => t.GetParameters().Length).First();
return CreateInstance(type, ctor);
}
///
/// 构造函数注入
///
///
///
///
private object CreateInstance(RegisteredType type, ConstructorInfo ctor)
{
//获取构造函数参数
var paraArray = ctor.GetParameters();
if (paraArray.Length == 0)
{
return type.CreateInstance();
}
var parameters = new List
接下来测试一下
main函数
static void Main(string[] args)
{
var container = new MyContainer();
//依赖注入 瞬时默认
container.RegisterType();
var language1 = container.Resolve();
var language2 = container.Resolve();
Console.WriteLine($"-----------------------瞬时默认-------------------------");
Console.WriteLine($"language1 与 language2:{ReferenceEquals(language1, language2)}\r\n");
//线程单例
Console.WriteLine($"-----------------------线程单例-------------------------");
container.RegisterType(TypeLifeTime.PerThread);
ILanguage tlanguage1 = null;
var task1 = Task.Run(() => {
tlanguage1 = container.Resolve();
Console.WriteLine($"tlanguage1 线程id:{Thread.CurrentThread.ManagedThreadId}");
});
ILanguage tlanguage2 = null;
ILanguage tlanguage3 = null;
var task2 = Task.Run(() => {
tlanguage2 = container.Resolve();
tlanguage3 = container.Resolve();
Console.WriteLine($"tlanguage2 线程id:{Thread.CurrentThread.ManagedThreadId}");
Console.WriteLine($"tlanguage3 线程id:{Thread.CurrentThread.ManagedThreadId}");
});
task1.Wait();
task2.Wait();
Console.WriteLine($"tlanguage1 与 tlanguage2 :{ReferenceEquals(tlanguage1, tlanguage2)}");
Console.WriteLine($"tlanguage2 与 tlanguage3 :{ReferenceEquals(tlanguage2, tlanguage3)}\r\n");
//单例模式
container.RegisterType(TypeLifeTime.Singleton);
var slanguage1 = container.Resolve();
var slanguage2 = container.Resolve();
Console.WriteLine($"-----------------------单例模式-------------------------");
Console.WriteLine($"slanguage1 与 slanguage2:{ReferenceEquals(slanguage1, slanguage2)}");
Console.Read();
}
输出结果:
附上项目结构图:
文章就到这里了,还有很多功能未实现(如函数注入,属性注入等),主要为了了解学习IOC容器- -
项目源码:https://github.com/booker1/IOC