自定義IOC
為什么不直接用Core自帶的IOC?
1. 能夠理解本質(zhì)
2. 擴(kuò)展性更強(qiáng)
接上一章擴(kuò)展 : 《.Net Core 3.x MVC DIP與Factory》
這章完成目標(biāo):
1.多參數(shù)
2.多構(gòu)造函數(shù)(參數(shù)數(shù)量/特性標(biāo)識(shí))
開始擼碼
在 AspNetCore.IOCDI.Framework 添加 容器接口 和 容器實(shí)現(xiàn)類
容器實(shí)現(xiàn) 躯肌,這里容器實(shí)現(xiàn)了無限級(jí)遞歸春宣,和 特性標(biāo)記
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace AspNetCore.IOCDI.Framework.CustomContainer
{
/// <summary>
/// 用來生產(chǎn)對(duì)象
/// 第三方 業(yè)務(wù)無關(guān)性
/// </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 這個(gè)類型作為Value
this.CoreContainerDictionary.Add(typeof(TFrom).FullName,typeof(TTo));
}
/// <summary>
/// 用類型名稱找出類型澜建,返回 創(chuàng)建好的對(duì)象
/// </summary>
/// <typeparam name="TFrom"></typeparam>
/// <returns></returns>
public TFrom Resolve<TFrom>() {
return (TFrom)this.ResolveObject(typeof(TFrom));
}
/// <summary>
/// 遞歸--可以完成不限層級(jí)的東西
/// </summary>
private object ResolveObject(Type abstracttype)
{
string key = abstracttype.FullName;
Type type = this.CoreContainerDictionary[key];
#region 選擇適合的構(gòu)造函數(shù)
ConstructorInfo ctor = null;
//是否有標(biāo)記,有特性標(biāo)記用特性標(biāo)記剑令,沒有就用參數(shù)最多的
ctor = type.GetConstructors().FirstOrDefault(c => c.IsDefined(typeof(CoreConstructorAttribute), true));
if (ctor == null)
{
//找參數(shù)最多的
ctor = type.GetConstructors().OrderByDescending(c => c.GetParameters().Length).First();
}
#endregion
#region 準(zhǔn)備構(gòu)造函數(shù)的參數(shù)
List<object> paraList = new List<object>();
foreach (var para in ctor.GetParameters())
{
Type paraType = para.ParameterType;//獲取參數(shù)的類型 IUserDAL
object paraInstance = this.ResolveObject(paraType);
paraList.Add(paraInstance);
}
#endregion
object oInstance = Activator.CreateInstance(type, paraList.ToArray());
return oInstance;
}
}
}
添加接口 ITestServiceA , 和 ITestServiceB 都是只有 一個(gè) show() 接口TestServiceA 實(shí)現(xiàn)
using AspNetCore.IOCDI.Interface;
using System;
namespace AspNetCore.IOCDI.Service
{
public class TestServiceA : ITestServiceA
{
public TestServiceA() {
Console.WriteLine($"{ this.GetType().Name }被構(gòu)造拄查。吁津。。");
}
public void Show()
{
Console.WriteLine("這里是 TestServiceA Show.");
}
}
}
TestServiceB 實(shí)現(xiàn)
using AspNetCore.IOCDI.Interface;
using System;
namespace AspNetCore.IOCDI.Service
{
public class TestServiceB : ITestServiceB
{
public TestServiceB(ITestServiceA iTestServiceA) {
Console.WriteLine($"{ this.GetType().Name }被構(gòu)造堕扶。碍脏。。");
}
private ITestServiceA _iTestServiceA = null;
public void Init(ITestServiceA testServiceA) {
this._iTestServiceA = testServiceA;
}
public void Show()
{
Console.WriteLine("這里是 TestServiceB Show.");
}
}
}
修改DAL,添加一個(gè)特性的構(gòu)造函數(shù)稍算,一個(gè)多參數(shù)的構(gòu)造函數(shù)修改控制臺(tái)項(xiàng)目 Program.cs
直接調(diào)試運(yùn)行典尾,這里看到BLL沒有加特性,就獲取最多參數(shù)的構(gòu)造函數(shù)
取到構(gòu)造函數(shù)IDAL糊探,然后遞歸ResolveObject方法
進(jìn)入ResolveObject后檢測(cè)到DAL是設(shè)置了特性的钾埂,就只能找到ItestServiceA
調(diào)試就能看出是如何把構(gòu)造函數(shù)里的依賴類創(chuàng)建成對(duì)象的