仿照IOC容器Unity容器实现自定义IOC容器
1.实现思路
(1)首先提供一个接口,这个接口包括实现注册类型的泛型方法,以及实例化类型的方法:IDZBContainer
public interface IDZBContainer
{
/// <summary>
/// 注册类型
/// </summary>
/// <typeparam name="TFrom"></typeparam>
/// <typeparam name="TTo"></typeparam>
void RegisterType<TFrom, TTo>();
/// <summary>
/// 实例化类型
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
T Resolve<T>();
}
(2)提供一个类,用来具体实现:DZBContainer,在注册类型的时候,通过一个字典将所有需要注册的类型放入其中
在创建对象时,有几个点需要注意,如果有多个构造函数,需要构造那个构造函数,这时候就需要提供一个特性来区分,如:
DZBInjectionConstructorAttribute,默认走参数最多的,参数类型构造是还要判断参数,这时候就需要采用递归的方式进行创建。如(3)
public class DZBContainer : IDZBContainer
{
/// <summary>
/// 提供一个字典将所有需要注册的类型放入
/// </summary>
private Dictionary<string, Type> DZBContainerDictionary = new Dictionary<string, Type>();
public void RegisterType<TFrom, TTo>()
{
DZBContainerDictionary.Add(typeof(TFrom).FullName, typeof(TTo));
}
public T Resolve<T>()
{
Type type = DZBContainerDictionary[typeof(T).FullName];
//通过递归的方式,来创建对象
return (T)this.CreateObject(type);
}
}
[AttributeUsage(AttributeTargets.Constructor)]
public sealed class DZBInjectionConstructorAttribute:Attribute
{
public DZBInjectionConstructorAttribute()
{ }
}
(3)通过递归的方式,来创建对象
private object CreateObject(Type type)
{
ConstructorInfo[] ctorArray = type.GetConstructors();
ConstructorInfo ctor = null;
//如果定义了DZBInjectionConstructorAttribute特性,则使用这个构造函数,否则寻找参数最多的构造函数
if (ctorArray.Count(c => c.IsDefined(typeof(DZBInjectionConstructorAttribute), true)) > 0)
{
ctor = ctorArray.FirstOrDefault(c => c.IsDefined(typeof(DZBInjectionConstructorAttribute), true));
}
else
{
ctor = ctorArray.OrderByDescending(c => c.GetParameters().Length).FirstOrDefault();
}
List<object> paraList = new List<object>();
foreach (var parameter in ctor.GetParameters())
{
Type paraType = parameter.ParameterType;
Type targetType = this.DZBContainerDictionary[paraType.FullName];
object para = this.CreateObject(targetType);
//递归:隐形的跳出条件,就是GetParameters结果为空,targetType拥有无参数构造函数
paraList.Add(para);
}
return Activator.CreateInstance(type, paraList.ToArray());
}
2.程序上端应用
IDZBContainer container = new DZBContainer();
container.RegisterType<DbContext, JDDbContext>();
container.RegisterType<IBaseService, BaseService>();
container.RegisterType<ICategoryCommodityService, CategoryCommodityService>();
ICategoryCommodityService categoryCommodityService = container.Resolve<ICategoryCommodityService>();