设计通过反射实现依赖注入
class Program
{
//获取到当前程序的程序集,并且获取元数据信息
public static Assembly assembly = Assembly.GetCallingAssembly();
static void Main(string[] args)
{
var types = assembly.GetTypes();
var DI = new DependencyInjectionTest();
Type type = typeof(MyClass);
var res = DI.StartASPNETCORE(type, "Action", types, "Eson", "Liu");
Console.WriteLine(res);
}
上面代码的作用是,获取到当前程序的程序集,并且获取元数据信息。
这是反射第一步。
1.1 构建依赖注入过程
/// <summary>
/// 接口
/// </summary>
public interface ITest
{
string Add(string a, string b);
}
/// <summary>
/// 实现
/// </summary>
public class Test : ITest
{
public string Add(string a, string b)
{
Console.WriteLine("Add方法被调用执行");
return a + b;
}
}
使用依赖注入
public class MyClass
{
private ITest _test;
public MyClass(ITest test)
{
_test = test;
}
public string Action(string a, string b)
{
Console.WriteLine("Action方法执行");
return _test.Add(a, b);
}
}
1.2 依赖实例化
获取一个类型的构造函数中,所有参数信息,并且为每一个类型实现自动创建实例.
传入参数:需要进行依赖注入的类型的 Type。
返回数据:构造函数参数的实例对象列表(反射都是object)。
/// <summary>
/// 实例化依赖
/// </summary>
/// <param name="type">要被实例化依赖注入的类型</param>
/// <param name="types">当前程序集的元数据类型</param>
public object[] CreateType(Type type, Type[] types)
{
// 这里只使用一个构造函数
ConstructorInfo? constructor = type.GetConstructors().FirstOrDefault();
// 获取类型的构造的函数参数
ParameterInfo[] paramList = constructor.GetParameters();
// 依赖注入的对象列表
List<object> objectList = new List<object>();
foreach (ParameterInfo item in paramList)
{
//获取参数类型:item.ParameterType.Name
//获取程序中,哪个类型实现了 item 的接口
Type? who = types.FirstOrDefault(x => x.GetInterfaces().Any(z => z.Name == item.ParameterType.Name));
//实例化
object? create = Activator.CreateInstance(who);
if (create != null) objectList.Add(create);
}
return objectList.ToArray();
}
1.3 实例化类型、依赖注入、调用方法
目前来到了依赖注入的最后阶段,实例化一个类型、注入依赖、调用方法。
/// <summary>
/// 实现依赖注入、调用方法
/// </summary>
/// <param name="type">类型</param>
/// <param name="actionName">方法名称</param>
/// <param name="paramList">调用方法的参数列表</param>
/// <returns></returns>
public object StartASPNETCORE(Type type, string actionName, Type[] types, params object[] paramList)
{
// 获取 Action 重载方法
// 名字一样,参数个数一致
MethodInfo? method = type.GetMethods().FirstOrDefault(x => x.Name.ToLower() == actionName.ToLower()
&& x.GetParameters().Length == paramList.Length);
// 实例化MyClass
// 通过 CreateType 方法,拿到已经实例化类型的构造函数的参数对象
object[]? inject = CreateType(type, types);
// 注入依赖,实例化对象
object? example = Activator.CreateInstance(type, inject);
// 执行方法并且返回执行结果
object result;
result = method.Invoke(example, paramList);
return result;
}
通过 CreateType 方法,已经拿到实例化类型的构造函数的参数对象了。这里确定调用哪个重载方法的方式,是通过参数的多少,因为这里控制台输入只能获取 string。
流程图