Files
serein-flow/Library/Utils/SereinIoc.cs

799 lines
29 KiB
C#
Raw Normal View History

using Microsoft.CodeAnalysis.CSharp.Syntax;
using Serein.Library.Api;
using System;
2024-08-06 15:41:14 +08:00
using System.Collections.Concurrent;
using System.Collections.Generic;
2024-09-30 16:36:55 +08:00
using System.Diagnostics;
using System.Linq;
2024-08-06 15:41:14 +08:00
using System.Reflection;
using System.Text;
2024-08-06 15:41:14 +08:00
namespace Serein.Library.Utils
2024-08-06 15:41:14 +08:00
{
/// <summary>
/// 一个轻量级的IOC容器
/// </summary>
public class SereinIOC : ISereinIOC
2024-08-06 15:41:14 +08:00
{
/// <summary>
/// 类型集合,暂放待实例化的类型,完成实例化之后移除
/// </summary>
private readonly ConcurrentDictionary<string, Type> _typeMappings;
/// <summary>
/// 已完成注入的实例集合
/// </summary>
2024-08-06 15:41:14 +08:00
private readonly ConcurrentDictionary<string, object> _dependencies;
/// <summary>
/// 能够获取类型实例的闭包
/// </summary>
private readonly ConcurrentDictionary<string, Func<object>> _registerCallback;
2025-07-07 20:40:24 +08:00
/// <summary>
/// 未完成注入的实例集合。
/// 键:需要的类型名称
/// 值:元组(对象实例,对象的属性)
/// </summary>
private readonly ConcurrentDictionary<string, List<(object,PropertyInfo)>> _unfinishedDependencies;
/// <summary>
/// IOC容器成功创建了类型
/// </summary>
2024-09-26 21:00:17 +08:00
public event IOCMembersChangedHandler OnIOCMembersChanged;
2024-08-06 15:41:14 +08:00
/// <summary>
/// 一个轻量级的IOC容器
/// </summary>
public SereinIOC()
2024-08-06 15:41:14 +08:00
{
_dependencies = new ConcurrentDictionary<string, object>();
_registerCallback = new ConcurrentDictionary<string, Func<object>>();
_typeMappings = new ConcurrentDictionary<string, Type>();
_unfinishedDependencies = new ConcurrentDictionary<string, List<(object, PropertyInfo)>>();
2024-08-06 15:41:14 +08:00
}
#region
/// <summary>
/// 向容器注册类型
/// </summary>
/// <param name="type">需要注册的类型</param>
/// <returns></returns>
public ISereinIOC Register(Type type)
{
RegisterType(type.FullName, type);
return this;
}
2024-08-06 15:41:14 +08:00
/// <summary>
/// 向容器注册类型,并指定其实例成员
/// </summary>
/// <param name="type">需要注册的类型</param>
/// <param name="getInstance">获取实例的回调函数</param>
/// <returns></returns>
public ISereinIOC Register(Type type, Func<object> getInstance)
2024-08-06 15:41:14 +08:00
{
RegisterType(type.FullName, type, getInstance);
return this;
2024-08-06 15:41:14 +08:00
}
/// <summary>
/// 向容器注册类型,并指定其实例成员
/// </summary>
/// <typeparam name="T">需要注册的类型</typeparam>
/// <returns></returns>
public ISereinIOC Register<T>()
{
var type = typeof(T);
RegisterType(type.FullName, type);
return this;
}
/// <summary>
/// 向容器注册类型,并指定其实例成员
/// </summary>
/// <typeparam name="T">需要注册的类型</typeparam>
/// <param name="getInstance">获取实例的回调函数</param>
/// <returns></returns>
public ISereinIOC Register<T>(Func<T> getInstance)
2024-08-06 15:41:14 +08:00
{
var type = typeof(T);
RegisterType(type.FullName, type, () => getInstance.Invoke());
return this;
2024-08-06 15:41:14 +08:00
}
/// <summary>
/// 向容器注册接口类型,并指定其实例成员
/// </summary>
/// <typeparam name="TService">接口类型</typeparam>
/// <typeparam name="TImplementation">实现类类型</typeparam>
/// <param name="getInstance">获取实例的方法</param>
/// <returns></returns>
public ISereinIOC Register<TService, TImplementation>(Func<TService> getInstance)
2024-08-06 15:41:14 +08:00
where TImplementation : TService
{
2025-07-07 20:40:24 +08:00
RegisterType(typeof(TService).FullName, typeof(TImplementation), () => getInstance.Invoke());
return this;
}
/// <summary>
/// 向容器注册接口类型,其实例成员由容器自动创建
/// </summary>
/// <typeparam name="TService">接口类型</typeparam>
/// <typeparam name="TImplementation">实现类类型</typeparam>
/// <returns></returns>
public ISereinIOC Register<TService, TImplementation>()
where TImplementation : TService
{
2025-07-07 20:40:24 +08:00
RegisterType(typeof(TService).FullName, typeof(TImplementation));
return this;
}
#endregion
2024-08-06 15:41:14 +08:00
2025-07-07 20:40:24 +08:00
#region
/// <summary>
/// 用于临时实例的创建不登记到IOC容器中依赖项注入失败时也不记录。
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public object CreateObject(Type type)
{
var ctors = GetConstructor(type); // 获取构造函数
object instance = null;
// 从入参最多的构造函数开始构建对象
foreach (var ctor in ctors)
{
var parameters = ctor.GetParameters(); // 获取构造函数参数列表
var parametersNames = parameters.Select(p => $"{p.ParameterType} {p.Name}");
var parametersName = string.Join(", ", parametersNames);
try
{
var parameterValues = parameters.Select(param => Get(param.ParameterType)).ToArray(); // 生成创建类型的入参参数
instance = Activator.CreateInstance(type, parameterValues); // 创建实例
}
catch (Exception ex)
{
Debug.WriteLine(ex);
SereinEnv.WriteLine(InfoType.INFO, $"在【{type}】类型上使用ctor({parametersName})构造函数时创建对象失败。错误信息:{ex.Message}");
continue;
}
InjectDependencies(instance, false); // 完成创建后注入实例需要的特性依赖项
break;
}
if (instance == null)
{
throw new Exception($"无法为【{type}】类型创建实例");
}
return instance;
}
2024-08-06 15:41:14 +08:00
2024-09-26 21:00:17 +08:00
/// <summary>
/// 用于临时实例的创建不登记到IOC容器中依赖项注入失败时也不记录。
2024-09-26 21:00:17 +08:00
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public T CreateObject<T>()
{
return (T)CreateObject(typeof(T));
}
/// <summary>
/// 给定一个实例,尽可能地在该实例中具有[AutoInjection]特性的属性/字段上设置为IOC容器中已有的对应类型的对象。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="instance"></param>
/// <returns></returns>
public T InjectDependenciesProperty<T>(T instance)
{
var type = instance.GetType();
var properties = type.GetType()
.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).ToArray()
.Where(p => p.CanWrite // 可写属性
&& p.GetCustomAttribute<AutoInjectionAttribute>() != null // 有特性标注需要注入
&& p.GetValue(instance) == null); // 属性为空
// 属性注入
foreach (var property in properties)
{
var propertyType = property.PropertyType;
if (_dependencies.TryGetValue(propertyType.FullName, out var dependencyInstance))
{
property.SetValue(instance, dependencyInstance); // 尝试写入到目标实例的属性中
}
}
// 字段注入
var fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic )
.Where(f => f.GetCustomAttribute<AutoInjectionAttribute>() != null
&& f.GetValue(instance) == null);
foreach (var field in fields)
{
var fieldType = field.FieldType;
if (_dependencies.TryGetValue(fieldType.FullName, out var dependencyInstance))
{
field.SetValue(instance, dependencyInstance);
}
}
return instance;
}
#endregion
#region
/// <summary>
/// 尝试获取指定类型的示例
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public object Get(Type type)
{
var instance = Get(type.FullName);
if(instance is null)
{
SereinEnv.WriteLine(InfoType.INFO, "类型没有注册:" + type.FullName);
}
return Get(type.FullName);
}
/// <summary>
/// 尝试获取指定类型的示例
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public T Get<T>()
{
return (T)Get(typeof(T).FullName);
}
private object Get(string name)
{
if (!_dependencies.TryGetValue(name, out object value))
{
value = null;
}
return value;
}
#endregion
#region
/// <summary>
/// 清空容器对象
/// </summary>
/// <returns></returns>
public ISereinIOC Reset()
2024-08-06 15:41:14 +08:00
{
// 检查是否存在非托管资源
foreach (var instancei in _dependencies.Values)
2024-08-06 15:41:14 +08:00
{
if (typeof(IDisposable).IsAssignableFrom(instancei.GetType()) && instancei is IDisposable disposable)
{
disposable?.Dispose();
}
2024-08-06 15:41:14 +08:00
}
_registerCallback?.Clear();
_unfinishedDependencies?.Clear();
_typeMappings?.Clear();
_dependencies?.Clear();
return this;
2024-08-06 15:41:14 +08:00
}
class TypeKeyValue
2024-08-06 15:41:14 +08:00
{
2024-09-30 16:36:55 +08:00
public TypeKeyValue(string name, Type type)
2024-08-06 15:41:14 +08:00
{
2024-09-30 16:36:55 +08:00
this.Type = type;
this.Name = name;
2024-08-06 15:41:14 +08:00
}
2024-09-30 16:36:55 +08:00
public string Name { get; set; }
public Type Type { get; set; }
}
private const string IOC_MAIN = "*Priority Instantiation*";
/// <summary>
/// <para>遍历所有需要注册的类型,获取到它们所有构造函数,并统计每个构造函数的入参类型,构建依赖关系树</para>
/// </summary>
/// <returns>“ID-PID”关系的树形结构</returns>
private Dictionary<string, List<string>> BuildDependencyTree()
{
var dependencyMap = new Dictionary<string, HashSet<string>>();
dependencyMap[IOC_MAIN] = new HashSet<string>(); // 优先实例化
2024-09-30 16:36:55 +08:00
foreach (var typeMapping in _typeMappings)
{
var typeFullName = typeMapping.Key; // 注册的类型 FullName
var type = typeMapping.Value; // 对应的Type。如果是以接口形式注册typeFullName将是接口类的FullName而type将是接口实现类。
var constructors = GetConstructor(type); // 获取构造函数
if(constructors .Length == 0)
{
if (!dependencyMap[IOC_MAIN].Contains(type.FullName))
{
//dependencyMap[IOC_MAIN].Add(type.FullName);
dependencyMap[IOC_MAIN].Add(typeFullName);
}
}
foreach (var constructor in constructors)
{
if (constructor is null)
{
continue;
}
var parameters = constructor.GetParameters().Select(p => p.ParameterType);
var ctorCount = constructors.Length;
var ctorParamCount = parameters.Count();
// 类型仅有一个构造函数,并且无参,将优先实例化
if (ctorCount == 1 && ctorParamCount == 0)
{
if (!dependencyMap[IOC_MAIN].Contains(type.FullName))
{
2025-07-07 20:40:24 +08:00
//dependencyMap[IOC_MAIN].Add(type.FullName);
dependencyMap[IOC_MAIN].Add(typeFullName);
}
continue;
}
// 从类型的有参构造函数中提取类型
foreach (var param in parameters)
{
if (!dependencyMap.TryGetValue(param.FullName, out var hashSet))
{
hashSet = new HashSet<string>();
hashSet.Add(typeMapping.Key);
dependencyMap.Add(param.FullName, hashSet);
}
else
{
if (!hashSet.Contains(typeMapping.Key))
{
hashSet.Add(typeMapping.Key);
}
}
}
}
}
var tmp = dependencyMap.ToDictionary(key => key.Key, value => value.Value.ToList());
return tmp;
2024-09-30 16:36:55 +08:00
}
/// <summary>
/// 获取类型的所有构造函数,根据入参数量,由多到少排列
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
private ConstructorInfo[] GetConstructor(Type type)
{
return type.GetConstructors().OrderByDescending(ctor => ctor.GetParameters().Length).ToArray();
}
/// <summary>
/// 创建实例的生成顺序
/// </summary>
/// <param name="dependencyMap">依赖关系树</param>
/// <returns></returns>
2024-09-30 16:36:55 +08:00
public List<string> GetCreationOrder(Dictionary<string, List<string>> dependencyMap)
{
var graph = new Dictionary<string, List<string>>(); // 另一种依赖关系树
var indegree = new Dictionary<string, int>(); // 表示出现次数
2024-09-30 16:36:55 +08:00
foreach (var entry in dependencyMap)
{
// “rootNode”是注册类的类型FullName属性
var rootNode = entry.Key; // 根节点
if (!graph.ContainsKey(rootNode))
{
graph[rootNode] = new List<string>();
2024-09-30 16:36:55 +08:00
}
// “childNode”是注册类构造函数中出现过的参数的类型FullName属性
foreach (var childNode in entry.Value)
2024-09-30 16:36:55 +08:00
{
if (!graph.ContainsKey(childNode))
2024-09-30 16:36:55 +08:00
{
graph[childNode] = new List<string>();
2024-09-30 16:36:55 +08:00
}
graph[rootNode].Add(childNode);
2024-09-30 16:36:55 +08:00
// 更新入度
if (!indegree.ContainsKey(childNode))
2024-09-30 16:36:55 +08:00
{
indegree[childNode] = 0;
2024-09-30 16:36:55 +08:00
}
indegree[childNode]++;
}
2024-09-30 16:36:55 +08:00
if (!indegree.ContainsKey(rootNode))
{
indegree[rootNode] = 0;
}
}
2024-09-30 16:36:55 +08:00
// 拓扑排序
var creationOrder = new List<string>();
var queue = new Queue<string>(indegree.Where(x => x.Value == 0).Select(x => x.Key));
while (queue.Count > 0)
{
var current = queue.Dequeue();
creationOrder.Add(current);
foreach (var neighbor in graph[current])
{
indegree[neighbor]--;
if (indegree[neighbor] == 0)
{
queue.Enqueue(neighbor);
}
}
}
var tmpList = indegree.Where(kv => kv.Value > 0).Select(kv => kv.Key).ToList();
if (tmpList.Count > 0)
{
StringBuilder sb = new StringBuilder();
sb.Append("以下类型存在循环依赖,请避免循环依赖,如果确实需要循环引用,请使用 [AutoInjection] 特性注入属性");
foreach (var kv in tmpList)
{
sb.AppendLine($"类名 : {kv}");
}
SereinEnv.WriteLine(InfoType.ERROR, sb.ToString());
}
2024-09-30 16:36:55 +08:00
return creationOrder;
}
/// <summary>
/// 创建实例对象
/// </summary>
/// <param name="typeName"></param>
/// <returns></returns>
private object CreateInstance(string typeName)
{
2025-07-07 20:40:24 +08:00
if (!_typeMappings.TryGetValue(typeName, out var type)) // 获取类型
{
return null;
}
if (_dependencies.TryGetValue(typeName, out var instance)) // 获取实例
{
return instance;
}
if (_registerCallback.TryGetValue(typeName,out var getInstance))
{
return getInstance.Invoke();
}
// 字符串、值类型,抽象类型,暂时不支持自动创建
if (type == typeof(string) || type.IsValueType || type.IsAbstract)
{
return null;
}
else
{
// 没有显示指定构造函数入参,选择参数最多的构造函数
//var constructor = GetConstructorWithMostParameters(type);
var constructors = GetConstructor(type); // 获取构造函数
foreach(var constructor in constructors)
{
var parameters = constructor.GetParameters();
var args = new object[parameters.Length];
for (int i = 0; i < parameters.Length; i++)
{
var argType = parameters[i].ParameterType;
var fullName = parameters[i].ParameterType.FullName;
if (!_dependencies.TryGetValue(fullName, out var argObj))
{
if (!_typeMappings.ContainsKey(fullName))
{
_typeMappings.TryAdd(fullName, argType);
}
argObj = CreateInstance(fullName);
if (argObj is null)
{
SereinEnv.WriteLine(InfoType.WARN, "构造参数创建失败");
continue;
}
}
args[i] = argObj;
}
try
{
instance = Activator.CreateInstance(type, args);
if(instance != null)
{
break;
}
}
catch (Exception)
{
continue;
}
}
}
InjectDependencies(instance); // 完成创建后注入实例需要的特性依赖项
_dependencies[typeName] = instance;
return instance;
2024-09-30 16:36:55 +08:00
}
/// <summary>
/// 绑定所有类型,生成示例
/// </summary>
/// <returns></returns>
public ISereinIOC Build()
2024-09-30 16:36:55 +08:00
{
2025-07-07 20:40:24 +08:00
Dictionary<string, List<string>> dependencyTree = BuildDependencyTree(); // 生成类型依赖关系
List<string> creationOrder = GetCreationOrder(dependencyTree); // 生成创建顺序
2024-09-30 16:36:55 +08:00
// 输出创建顺序
Debug.WriteLine("创建顺序: " + string.Join($"{Environment.NewLine}↓ {Environment.NewLine}", creationOrder));
2024-09-30 16:36:55 +08:00
// 创建对象
foreach (var typeName in creationOrder)
{
2025-07-07 20:40:24 +08:00
if (typeName.Equals("Serein.Library.LightweightFlowEnvironment"))
{
}
2024-09-30 16:36:55 +08:00
if (_dependencies.ContainsKey(typeName))
{
2024-09-30 16:36:55 +08:00
continue;
}
2025-07-04 15:46:29 +08:00
if(typeName == IOC_MAIN)
{
continue;
}
2024-09-30 16:36:55 +08:00
var value = CreateInstance(typeName);
2025-07-07 20:40:24 +08:00
if (value is null)
{
SereinEnv.WriteLine(InfoType.ERROR, $"IOC容器无法创建对象{typeName}");
continue;
}
2024-09-30 16:36:55 +08:00
_dependencies[typeName] = value;
OnIOCMembersChanged?.Invoke(new IOCMembersChangedEventArgs(typeName, value));
2025-07-07 20:40:24 +08:00
}
2024-09-30 16:36:55 +08:00
_typeMappings.Clear();
return this;
}
2024-09-30 16:36:55 +08:00
#endregion
2024-08-06 15:41:14 +08:00
#region
/// <summary>
/// 注册类型
/// </summary>
/// <param name="typeFull">类型名称</param>
/// <param name="type">要注册的类型</param>
/// <param name="getInstance">获取实例的闭包</param>
private bool RegisterType(string typeFull, Type type, Func<object> getInstance = null)
2024-08-06 15:41:14 +08:00
{
if (!_typeMappings.ContainsKey(typeFull))
{
_typeMappings[typeFull] = type;
if(getInstance != null)
{
_registerCallback[typeFull] = getInstance;
}
return true;
}
else
{
return false;
}
}
2024-08-06 15:41:14 +08:00
/// <summary>
/// 如果其它实例想要该对象时,注入过去
/// </summary>
private void InjectUnfinishedDependencies(string key, object instance)
2024-09-26 21:00:17 +08:00
{
if (_unfinishedDependencies.TryGetValue(key, out var unfinishedPropertyList))
{
foreach ((object obj, PropertyInfo property) in unfinishedPropertyList)
{
property.SetValue(obj, instance); //注入依赖项
}
2024-09-26 21:00:17 +08:00
if (_unfinishedDependencies.TryRemove(key, out unfinishedPropertyList))
{
unfinishedPropertyList.Clear();
}
}
}
/// <summary>
/// 注入目标实例的依赖项
/// </summary>
/// <param name="instance">实例</param>
/// <param name="isRecord">未完成依赖项注入时是否记录</param>
private bool InjectDependencies(object instance,bool isRecord = true)
{
var properties = instance.GetType()
.GetProperties(BindingFlags.Instance | BindingFlags.Public).ToArray()
.Where(p => p.CanWrite // 可写属性
&& p.GetCustomAttribute<AutoInjectionAttribute>() != null // 有特性标注需要注入
&& p.GetValue(instance) == null); // 属性为空
var isPass = true;
2024-08-06 15:41:14 +08:00
foreach (var property in properties)
{
var propertyType = property.PropertyType;
// 通过属性类型名称从ioc容器中获取对应的实例
2024-08-06 15:41:14 +08:00
if (_dependencies.TryGetValue(propertyType.FullName, out var dependencyInstance))
{
property.SetValue(instance, dependencyInstance); // 尝试写入到目标实例的属性中
}
else if( isRecord )
{
// 存在依赖项,但目标类型的实例暂未加载,需要等待需要实例完成注册
var unfinishedDependenciesList = _unfinishedDependencies.GetOrAdd(propertyType.FullName, _ = new List<(object, PropertyInfo)>());
var data = (instance, property);
if (!unfinishedDependenciesList.Contains(data))
{
unfinishedDependenciesList.Add(data);
}
isPass = false;
2024-08-06 15:41:14 +08:00
}
}
return isPass;
2024-08-06 15:41:14 +08:00
}
#endregion
#region
public ISereinIOC Run<T>(Action<T> action)
2024-08-06 15:41:14 +08:00
{
var service = Get<T>();
action(service);
return this;
2024-08-06 15:41:14 +08:00
}
public ISereinIOC Run<T1, T2>(Action<T1, T2> action)
2024-08-06 15:41:14 +08:00
{
var service1 = Get<T1>();
var service2 = Get<T2>();
2024-08-06 15:41:14 +08:00
action(service1, service2);
return this;
2024-08-06 15:41:14 +08:00
}
public ISereinIOC Run<T1, T2, T3>(Action<T1, T2, T3> action)
2024-08-06 15:41:14 +08:00
{
var service1 = Get<T1>();
var service2 = Get<T2>();
var service3 = Get<T3>();
2024-08-06 15:41:14 +08:00
action(service1, service2, service3);
return this;
2024-08-06 15:41:14 +08:00
}
public ISereinIOC Run<T1, T2, T3, T4>(Action<T1, T2, T3, T4> action)
2024-08-06 15:41:14 +08:00
{
var service1 = Get<T1>();
var service2 = Get<T2>();
var service3 = Get<T3>();
var service4 = Get<T4>();
2024-08-06 15:41:14 +08:00
action(service1, service2, service3, service4);
return this;
2024-08-06 15:41:14 +08:00
}
#endregion
}
/* public interface IServiceContainer
{
ServiceContainer Register<T>(params object[] parameters);
ServiceContainer Register<TService, TImplementation>(params object[] parameters) where TImplementation : TService;
TService Resolve<TService>();
void Get<T>(Action<T> action);
object Instantiate(Type type, params object[] parameters);
}
public class ServiceContainer : IServiceContainer
{
private readonly Dictionary<Type, object> _dependencies;
public ServiceContainer()
{
_dependencies = new Dictionary<Type, object>
{
[typeof(IServiceContainer)] = this
};
}
public void Get<T>(Action<T> action)
{
var service = Resolve<T>();
action(service);
}
public ServiceContainer Register<T>(params object[] parameters)
{
var instance = Instantiate(typeof(T), parameters);
_dependencies[typeof(T)] = instance;
return this;
}
public ServiceContainer Register<TService, TImplementation>(params object[] parameters)
where TImplementation : TService
{
_dependencies[typeof(TService)] = Instantiate(typeof(TImplementation), parameters);
return this;
}
public TService Resolve<TService>()
{
return (TService)_dependencies[typeof(TService)];
}
public object Instantiate(Type controllerType, params object[] parameters)
{
var constructors = controllerType.GetConstructors(); // 获取控制器的所有构造函数
// 查找具有最多参数的构造函数
var constructor = constructors.OrderByDescending(c => c.GetParameters().Length).FirstOrDefault();
if (constructor != null)
{
if (parameters.Length > 0)
{
return Activator.CreateInstance(controllerType, parameters);
}
else {
var tmpParameters = constructor.GetParameters();
var dependencyInstances = new List<object>();
foreach (var parameter in tmpParameters)
{
var parameterType = parameter.ParameterType;
_dependencies.TryGetValue(parameterType, out var dependencyInstance);
dependencyInstances.Add(dependencyInstance);
if (dependencyInstance == null)
{
return null;
}
}
// 用解析的依赖项实例化目标类型
return Activator.CreateInstance(controllerType, dependencyInstances.ToArray());
}
}
else
{
return Activator.CreateInstance(controllerType);
}
}
}*/
}