自定义IOC
为什么不直接用Core自带的IOC?
1. 能够理解本质
2. 扩展性更强
接上一章扩展 : 《.Net Core 3.x MVC DIP与Factory》
这章完成目标:
1.多参数
2.多构造函数(参数数量/特性标识)
开始撸码
在 AspNetCore.IOCDI.Framework 添加 容器接口 和 容器实现类
容器实现 ,这里容器实现了无限级递归,和 特性标记
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace AspNetCore.IOCDI.Framework.CustomContainer
{
/// <summary>
/// 用来生产对象
/// 第三方 业务无关性
/// </summary>
public class CoreContainer: ICoreContainer
{
private Dictionary<string, Type> CoreContainerDictionary = new Dictionary<string, Type>();
/// <summary>
/// where TTo 必须是 TFrom 类型的约束
/// </summary>
public void Register<TFrom, TTo>() where TTo: TFrom
{
//用TFrom的名称作为Key ,用 TTo 这个类型作为Value
this.CoreContainerDictionary.Add(typeof(TFrom).FullName,typeof(TTo));
}
/// <summary>
/// 用类型名称找出类型,返回 创建好的对象
/// </summary>
/// <typeparam name="TFrom"></typeparam>
/// <returns></returns>
public TFrom Resolve<TFrom>() {
return (TFrom)this.ResolveObject(typeof(TFrom));
}
/// <summary>
/// 递归--可以完成不限层级的东西
/// </summary>
private object ResolveObject(Type abstracttype)
{
string key = abstracttype.FullName;
Type type = this.CoreContainerDictionary[key];
#region 选择适合的构造函数
ConstructorInfo ctor = null;
//是否有标记,有特性标记用特性标记,没有就用参数最多的
ctor = type.GetConstructors().FirstOrDefault(c => c.IsDefined(typeof(CoreConstructorAttribute), true));
if (ctor == null)
{
//找参数最多的
ctor = type.GetConstructors().OrderByDescending(c => c.GetParameters().Length).First();
}
#endregion
#region 准备构造函数的参数
List<object> paraList = new List<object>();
foreach (var para in ctor.GetParameters())
{
Type paraType = para.ParameterType;//获取参数的类型 IUserDAL
object paraInstance = this.ResolveObject(paraType);
paraList.Add(paraInstance);
}
#endregion
object oInstance = Activator.CreateInstance(type, paraList.ToArray());
return oInstance;
}
}
}
添加接口 ITestServiceA , 和 ITestServiceB 都是只有 一个 show() 接口TestServiceA 实现
using AspNetCore.IOCDI.Interface;
using System;
namespace AspNetCore.IOCDI.Service
{
public class TestServiceA : ITestServiceA
{
public TestServiceA() {
Console.WriteLine($"{ this.GetType().Name }被构造。。。");
}
public void Show()
{
Console.WriteLine("这里是 TestServiceA Show.");
}
}
}
TestServiceB 实现
using AspNetCore.IOCDI.Interface;
using System;
namespace AspNetCore.IOCDI.Service
{
public class TestServiceB : ITestServiceB
{
public TestServiceB(ITestServiceA iTestServiceA) {
Console.WriteLine($"{ this.GetType().Name }被构造。。。");
}
private ITestServiceA _iTestServiceA = null;
public void Init(ITestServiceA testServiceA) {
this._iTestServiceA = testServiceA;
}
public void Show()
{
Console.WriteLine("这里是 TestServiceB Show.");
}
}
}
修改DAL,添加一个特性的构造函数,一个多参数的构造函数修改控制台项目 Program.cs
直接调试运行,这里看到BLL没有加特性,就获取最多参数的构造函数
取到构造函数IDAL,然后递归ResolveObject方法
进入ResolveObject后检测到DAL是设置了特性的,就只能找到ItestServiceA
调试就能看出是如何把构造函数里的依赖类创建成对象的