Files
serein-flow/Library/Utils/SereinIoc.cs
2024-10-11 19:31:34 +08:00

660 lines
23 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Newtonsoft.Json.Linq;
using Serein.Library.Api;
using Serein.Library.Attributes;
using Serein.Library.Web;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Xml;
using System.Xml.Schema;
namespace Serein.Library.Utils
{
/// <summary>
/// IOC管理容器
/// </summary>
public class SereinIOC/* : ISereinIOC*/
{
/// <summary>
/// 类型集合,暂放待实例化的类型,完成实例化之后移除
/// </summary>
private readonly ConcurrentDictionary<string, Type> _typeMappings;
/// <summary>
/// 已完成注入的实例集合
/// </summary>
private readonly ConcurrentDictionary<string, object> _dependencies;
private readonly ConcurrentDictionary<string, object[]> _registerParameterss;
/// <summary>
/// 未完成注入的实例集合。
/// 键:需要的类型名称
/// 值:元组(对象实例,对象的属性)
/// </summary>
private readonly ConcurrentDictionary<string, List<(object,PropertyInfo)>> _unfinishedDependencies;
public event IOCMembersChangedHandler OnIOCMembersChanged;
public SereinIOC()
{
_dependencies = new ConcurrentDictionary<string, object>();
_registerParameterss = new ConcurrentDictionary<string, object[]>();
_typeMappings = new ConcurrentDictionary<string, Type>();
_unfinishedDependencies = new ConcurrentDictionary<string, List<(object, PropertyInfo)>>();
}
#region
/// <summary>
/// 注册类型
/// </summary>
/// <param name="type">目标类型</param>
/// <param name="parameters">参数</param>
public bool Register(Type type, params object[] parameters)
{
return RegisterType(type?.FullName, type, parameters);
}
/// <summary>
/// 注册类型
/// </summary>
/// <param name="type">目标类型</param>
/// <param name="parameters">参数</param>
public bool Register<T>(params object[] parameters)
{
var type = typeof(T);
return RegisterType(type.FullName, type, parameters);
}
/// <summary>
/// 注册接口类型
/// </summary>
/// <param name="type">目标类型</param>
/// <param name="parameters">参数</param>
public bool Register<TService, TImplementation>(params object[] parameters)
where TImplementation : TService
{
return RegisterType(typeof(TService).FullName, typeof(TImplementation), parameters);
}
#endregion
/// <summary>
/// 用于临时实例的创建不登记到IOC容器中依赖项注入失败时也不记录。
/// </summary>
/// <param name="controllerType"></param>
/// <param name="parameters"></param>
/// <returns></returns>
public object Instantiate(Type type)
{
var constructor = type.GetConstructors().First(); // 获取第一个构造函数
var parameters = constructor.GetParameters(); // 获取参数列表
var parameterValues = parameters.Select(param => ResolveDependency(param.ParameterType)).ToArray();
var instance = Activator.CreateInstance(type, parameterValues);
//var instance =CreateInstance(controllerType, parameters); // CreateInstance(controllerType, parameters); // 创建目标类型的实例
if (instance != null)
{
InjectDependencies(instance, false); // 完成创建后注入实例需要的特性依赖项
}
return instance;
}
public T Instantiate<T>()
{
return (T)Instantiate(typeof(T));
}
#region
/// <summary>
/// 指定key值注册一个已经实例化的实例对象
/// </summary>
/// <param name="key"></param>
/// <param name="instance"></param>
/// <param name="needInjectProperty"></param>
public bool CustomRegisterInstance(string key, object instance, bool needInjectProperty = true)
{
// 不存在时才允许创建
if (_dependencies.ContainsKey(key))
{
return false;
}
_dependencies.TryAdd(key, instance);
if (needInjectProperty)
{
InjectDependencies(instance); // 注入实例需要的依赖项
}
InjectUnfinishedDependencies(key, instance); // 检查是否存在其它实例需要该类型
OnIOCMembersChanged?.Invoke(new IOCMembersChangedEventArgs(key, instance));
return true;
}
public object Get(Type type)
{
var instance = Get(type.FullName);
if(instance is null)
{
Console.WriteLine("类型没有注册:" + type.FullName);
}
return Get(type.FullName);
}
public T Get<T>()
{
return (T)Get(typeof(T).FullName);
}
public T Get<T>(string name)
{
return (T)Get(name);
}
private object Get(string name)
{
if (!_dependencies.TryGetValue(name, out object value))
{
value = null;
}
return value;
}
#endregion
#region
/// <summary>
/// 清空容器对象
/// </summary>
/// <returns></returns>
public bool Reset()
{
// 检查是否存在非托管资源
foreach (var instancei in _dependencies.Values)
{
if (typeof(IDisposable).IsAssignableFrom(instancei.GetType()) && instancei is IDisposable disposable)
{
disposable?.Dispose();
}
}
_registerParameterss?.Clear();
_unfinishedDependencies?.Clear();
_typeMappings?.Clear();
_dependencies?.Clear();
return true;
}
public class TypeKeyValue
{
public TypeKeyValue(string name, Type type)
{
this.Type = type;
this.Name = name;
}
public string Name { get; set; }
public Type Type { get; set; }
}
private const string FlowBaseClassName = "<>$FlowBaseClass!@#";
public Dictionary<string, List<string>> BuildDependencyTree()
{
var dependencyMap = new Dictionary<string, List<string>>();
//var tmpTypeFullName = new HashSet<string>();
//var tmpTypeFullName2 = new HashSet<string>();
dependencyMap[FlowBaseClassName] = new List<string>();
foreach (var typeMapping in _typeMappings)
{
var constructor = GetConstructorWithMostParameters(typeMapping.Value); // 获取参数最多的构造函数
if (constructor != null)
{
var parameters = constructor.GetParameters()
.Select(p => p.ParameterType)
.ToList();
//if(parameters.Count == 0)
//{
// if (!dependencyMap.ContainsKey(typeMapping.Value.FullName))
// {
// dependencyMap[typeMapping.Value.FullName] = new List<string>();
// }
// dependencyMap[typeMapping.Value.FullName].Add(typeMapping.Key);
//}
if(parameters .Count > 0)
{
// 从类型的构造函数中提取类型
foreach (var param in parameters)
{
if (!dependencyMap.ContainsKey(param.FullName))
{
dependencyMap[param.FullName] = new List<string>();
}
dependencyMap[param.FullName].Add(typeMapping.Key);
//tmpTypeFullName.Add(param.FullName);
//if (tmpTypeFullName2.Contains(param.FullName))
//{
// tmpTypeFullName2.Remove(param.FullName);
//}
}
}
else
{
var type = typeMapping.Value;
dependencyMap[FlowBaseClassName].Add(type.FullName);
}
}
}
return dependencyMap;
}
// 获取参数最多的构造函数
private ConstructorInfo GetConstructorWithMostParameters(Type type)
{
return type.GetConstructors()
.OrderByDescending(c => c.GetParameters().Length)
.FirstOrDefault();
}
// 生成顺序
public List<string> GetCreationOrder(Dictionary<string, List<string>> dependencyMap)
{
var graph = new Dictionary<string, List<string>>();
var indegree = new Dictionary<string, int>();
foreach (var entry in dependencyMap)
{
var key = entry.Key;
if (!graph.ContainsKey(key))
{
graph[key] = new List<string>();
}
foreach (var dependent in entry.Value)
{
if (!graph.ContainsKey(dependent))
{
graph[dependent] = new List<string>();
}
graph[key].Add(dependent);
// 更新入度
if (!indegree.ContainsKey(dependent))
{
indegree[dependent] = 0;
}
indegree[dependent]++;
}
if (!indegree.ContainsKey(key))
{
indegree[key] = 0;
}
}
// 拓扑排序
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)
{
Console.WriteLine("以下类型可能产生循环依赖,请避免循环依赖,如果确实需要循环引用,请使用 [AutoInjection] 特性注入属性");
foreach (var kv in tmpList)
{
Console.WriteLine($"Class Name : {kv}");
}
}
return creationOrder;
}
public object CreateInstance(string typeName)
{
if (!_typeMappings.TryGetValue(typeName, out var type))
{
return null;
}
if (_dependencies.TryGetValue(typeName, out var instance))
{
return instance;
}
if (_registerParameterss.TryGetValue(typeName,out var @params))
{
instance = Activator.CreateInstance(type, @params);
}
else
{
// 没有显示指定构造函数入参,选择参数最多的构造函数
var constructor = GetConstructorWithMostParameters(type);
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);
}
args[i] = argObj;
}
instance = Activator.CreateInstance(type, args);
}
InjectDependencies(instance); // 完成创建后注入实例需要的特性依赖项
_dependencies[typeName] = instance;
return instance;
}
public bool Build()
{
var dependencyTree = BuildDependencyTree();
var creationOrder = GetCreationOrder(dependencyTree);
// 输出创建顺序
Debug.WriteLine("创建顺序: " + string.Join(" → ", creationOrder));
// 创建对象
foreach (var typeName in creationOrder)
{
if (_dependencies.ContainsKey(typeName))
{
continue;
}
var value = CreateInstance(typeName);
if(value is null)
{
continue;
}
_dependencies[typeName] = value;
OnIOCMembersChanged.Invoke(new IOCMembersChangedEventArgs(typeName, value));
}
_typeMappings.Clear();
return true;
}
#endregion
#region
/// <summary>
/// 注册类型
/// </summary>
/// <param name="typeFull"></param>
/// <param name="type"></param>
private bool RegisterType(string typeFull, Type type, params object[] parameters)
{
if (!_typeMappings.ContainsKey(typeFull))
{
_typeMappings[typeFull] = type;
if(parameters.Length > 0)
{
_registerParameterss[typeFull] = parameters;
}
return true;
}
else
{
return false;
}
}
private object ResolveDependency(Type parameterType)
{
var obj = Get(parameterType);
if (obj is null)
{
throw new InvalidOperationException($"构造函数注入时类型[{parameterType}]不存在实例");
}
return obj;
}
/// <summary>
/// 如果其它实例想要该对象时,注入过去
/// </summary>
private void InjectUnfinishedDependencies(string key,object instance)
{
if (_unfinishedDependencies.TryGetValue(key, out var unfinishedPropertyList))
{
foreach ((object obj, PropertyInfo property) in unfinishedPropertyList)
{
property.SetValue(obj, instance); //注入依赖项
}
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;
foreach (var property in properties)
{
var propertyType = property.PropertyType;
// 通过属性类型名称从ioc容器中获取对应的实例
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;
}
}
return isPass;
}
public void Run<T>(Action<T> action)
{
var service = Get<T>();
action(service);
}
public void Run<T1, T2>(Action<T1, T2> action)
{
var service1 = Get<T1>();
var service2 = Get<T2>();
action(service1, service2);
}
public void Run<T1, T2, T3>(Action<T1, T2, T3> action)
{
var service1 = Get<T1>();
var service2 = Get<T2>();
var service3 = Get<T3>();
action(service1, service2, service3);
}
public void Run<T1, T2, T3, T4>(Action<T1, T2, T3, T4> action)
{
var service1 = Get<T1>();
var service2 = Get<T2>();
var service3 = Get<T3>();
var service4 = Get<T4>();
action(service1, service2, service3, service4);
}
public void Run<T1, T2, T3, T4, T5>(Action<T1, T2, T3, T4, T5> action)
{
var service1 = Get<T1>();
var service2 = Get<T2>();
var service3 = Get<T3>();
var service4 = Get<T4>();
var service5 = Get<T5>();
action(service1, service2, service3, service4, service5);
}
public void Run<T1, T2, T3, T4, T5, T6>(Action<T1, T2, T3, T4, T5, T6> action)
{
var service1 = Get<T1>();
var service2 = Get<T2>();
var service3 = Get<T3>();
var service4 = Get<T4>();
var service5 = Get<T5>();
var service6 = Get<T6>();
action(service1, service2, service3, service4, service5, service6);
}
public void Run<T1, T2, T3, T4, T5, T6, T7>(Action<T1, T2, T3, T4, T5, T6, T7> action)
{
var service1 = Get<T1>();
var service2 = Get<T2>();
var service3 = Get<T3>();
var service4 = Get<T4>();
var service5 = Get<T5>();
var service6 = Get<T6>();
var service7 = Get<T7>();
action(service1, service2, service3, service4, service5, service6, service7);
}
public void Run<T1, T2, T3, T4, T5, T6, T7, T8>(Action<T1, T2, T3, T4, T5, T6, T7, T8> action)
{
var service1 = Get<T1>();
var service2 = Get<T2>();
var service3 = Get<T3>();
var service4 = Get<T4>();
var service5 = Get<T5>();
var service6 = Get<T6>();
var service7 = Get<T7>();
var service8 = Get<T8>();
action(service1, service2, service3, service4, service5, service6, service7, service8);
}
#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);
}
}
}*/
}