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

490 lines
17 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 Serein.Library.Api;
using Serein.Library.Attributes;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Serein.Library.Utils
{
/// <summary>
/// IOC管理容器
/// </summary>
public class SereinIoc : ISereinIoc
{
/// <summary>
/// 实例集合
/// </summary>
private readonly ConcurrentDictionary<string, object> _dependencies;
/// <summary>
/// 未完成注入的实例集合。
/// 键:需要的类型名称
/// 值:对象实例(存储对象)
/// </summary>
private readonly ConcurrentDictionary<string, List<(object,PropertyInfo)>> _unfinishedDependencies;
/// <summary>
/// 类型集合
/// </summary>
private readonly ConcurrentDictionary<string, Type> _typeMappings;
/// <summary>
/// 待实例化的类型
/// </summary>
private readonly List<Type> _waitingForInstantiation;
public SereinIoc()
{
// 首先注册自己
_dependencies = new ConcurrentDictionary<string, object>
{
[typeof(ISereinIoc).FullName] = this
};
_typeMappings = new ConcurrentDictionary<string, Type>
{
[typeof(ISereinIoc).FullName] = typeof(ISereinIoc)
};
_unfinishedDependencies = new ConcurrentDictionary<string, List<(object, PropertyInfo)>>();
_waitingForInstantiation = new List<Type>();
}
/// <summary>
/// 获取或创建实例对象(不注入对象的依赖项)
/// </summary>
/// <param name="type">目标类型</param>
/// <param name="parameters">构造函数的参数</param>
/// <returns></returns>
public object GetOrCreateServiceInstance(Type type, params object[] parameters)
{
if (_dependencies.ContainsKey(type.FullName))
{
return _dependencies[type.FullName];
}
else
{
var instance = Activator.CreateInstance(type); // 创建目标类型的实例对象
InjectDependencies(instance);// 注入目标对象的依赖项
_dependencies[type.FullName] = instance; // 记录实例
return instance;
}
}
/// <summary>
/// 泛型方法, 获取或创建实例对象(不注入对象的依赖项)
/// </summary>
/// <typeparam name="T">目标类型</typeparam>
/// <param name="parameters">构造函数的参数</param>
/// <returns></returns>
public T GetOrCreateServiceInstance<T>(params object[] parameters)
{
return (T)GetOrCreateServiceInstance(typeof(T), parameters);
}
/// <summary>
/// 清空容器对象
/// </summary>
/// <returns></returns>
public ISereinIoc Reset()
{
// 检查是否存在非托管资源
foreach(var instancei in _dependencies.Values)
{
if (typeof(IDisposable).IsAssignableFrom(instancei.GetType()) && instancei is IDisposable disposable)
{
disposable.Dispose();
}
}
_typeMappings.Clear();
_dependencies.Clear();
_waitingForInstantiation.Clear();
return this;
}
/// <summary>
/// 注册类型
/// </summary>
/// <param name="type">目标类型</param>
/// <param name="parameters">参数</param>
public ISereinIoc Register(Type type, params object[] parameters)
{
RegisterType(type.FullName, type);
return this;
}
/// <summary>
/// 注册类型
/// </summary>
/// <param name="type">目标类型</param>
/// <param name="parameters">参数</param>
public ISereinIoc Register<T>(params object[] parameters)
{
var type = typeof(T);
RegisterType(type.FullName, type);
return this;
}
public ISereinIoc Register<TService, TImplementation>(params object[] parameters)
where TImplementation : TService
{
var typeFullName = typeof(TService).FullName;
RegisterType(typeFullName, typeof(TImplementation));
return this;
}
/// <summary>
/// 注册
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public object GetOrInstantiate(Type type)
{
if (!_dependencies.TryGetValue(type.FullName, out object value))
{
Register(type);
value = Instantiate(type);
InjectDependencies(type);
}
return value;
}
public T GetOrInstantiate<T>()
{
if(!_dependencies.TryGetValue(typeof(T).FullName, out object value))
{
Register(typeof(T));
value = Instantiate(typeof(T));
}
return (T)value;
//throw new InvalidOperationException("目标类型未创建实例");
}
/// <summary>
/// 实例化所有已注册的类型,并尝试绑定
/// </summary>
/// <returns></returns>
public ISereinIoc Build()
{
// 遍历已注册类型
foreach (var type in _typeMappings.Values.ToArray())
{
if(_dependencies.ContainsKey(type.FullName))
{
// 已经存在实例,不用管
}
else
{
// 如果没有创建实例,则创建对应的实例
_dependencies[type.FullName] = CreateInstance(type);
}
// 移除类型的注册记录
_typeMappings.TryRemove(type.FullName,out _);
}
// 注入实例的依赖项
foreach (var instance in _dependencies.Values)
{
InjectDependencies(instance);
}
//var instance = Instantiate(item.Value);
// TryInstantiateWaitingDependencies();
return this;
}
public object Instantiate(Type controllerType, params object[] parameters)
{
var instance = CreateInstance(controllerType, parameters);
if(instance != null)
{
InjectDependencies(instance);
}
return instance;
}
/// <summary>
/// 注册类型
/// </summary>
/// <param name="typeFull"></param>
/// <param name="type"></param>
private void RegisterType(string typeFull, Type type)
{
if (!_typeMappings.ContainsKey(typeFull))
{
_typeMappings[typeFull] = type;
}
}
/// <summary>
/// 创建实例时尝试注入到由ioc容器管理、并需要此实例的对象。
/// </summary>
private object CreateInstance(Type type, params object[] parameters)
{
var instance = Activator.CreateInstance(type);
if(_unfinishedDependencies.TryGetValue(type.FullName, out var unfinishedPropertyList))
{
foreach ((object obj, PropertyInfo property) in unfinishedPropertyList)
{
property.SetValue(obj, instance); //注入依赖项
}
if(_unfinishedDependencies.TryRemove(type.FullName, out unfinishedPropertyList))
{
unfinishedPropertyList.Clear();
}
}
return instance;
}
/// <summary>
/// 注入目标实例的依赖项
/// </summary>
/// <param name="instance"></param>
private bool InjectDependencies(object instance)
{
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
{
// 存在依赖项,但目标类型的实例暂未加载,需要等待需要实例完成注册
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;
}
/// <summary>
/// 再次尝试注入目标实例的依赖项
/// </summary>
private void TryInstantiateWaitingDependencies()
{
foreach (var waitingType in _waitingForInstantiation.ToList())
{
if (_typeMappings.TryGetValue(waitingType.FullName, out var implementationType))
{
var instance = Instantiate(implementationType);
if (instance != null)
{
_dependencies[waitingType.FullName] = instance;
_waitingForInstantiation.Remove(waitingType);
}
}
}
}
#region run()
public ISereinIoc Run<T>(Action<T> action)
{
var service = GetOrInstantiate<T>();
if (service != null)
{
action(service);
}
return this;
}
public ISereinIoc Run<T1, T2>(Action<T1, T2> action)
{
var service1 = GetOrInstantiate<T1>();
var service2 = GetOrInstantiate<T2>();
action(service1, service2);
return this;
}
public ISereinIoc Run<T1, T2, T3>(Action<T1, T2, T3> action)
{
var service1 = GetOrInstantiate<T1>();
var service2 = GetOrInstantiate<T2>();
var service3 = GetOrInstantiate<T3>();
action(service1, service2, service3);
return this;
}
public ISereinIoc Run<T1, T2, T3, T4>(Action<T1, T2, T3, T4> action)
{
var service1 = GetOrInstantiate<T1>();
var service2 = GetOrInstantiate<T2>();
var service3 = GetOrInstantiate<T3>();
var service4 = GetOrInstantiate<T4>();
action(service1, service2, service3, service4);
return this;
}
public ISereinIoc Run<T1, T2, T3, T4, T5>(Action<T1, T2, T3, T4, T5> action)
{
var service1 = GetOrInstantiate<T1>();
var service2 = GetOrInstantiate<T2>();
var service3 = GetOrInstantiate<T3>();
var service4 = GetOrInstantiate<T4>();
var service5 = GetOrInstantiate<T5>();
action(service1, service2, service3, service4, service5);
return this;
}
public ISereinIoc Run<T1, T2, T3, T4, T5, T6>(Action<T1, T2, T3, T4, T5, T6> action)
{
var service1 = GetOrInstantiate<T1>();
var service2 = GetOrInstantiate<T2>();
var service3 = GetOrInstantiate<T3>();
var service4 = GetOrInstantiate<T4>();
var service5 = GetOrInstantiate<T5>();
var service6 = GetOrInstantiate<T6>();
action(service1, service2, service3, service4, service5, service6);
return this;
}
public ISereinIoc Run<T1, T2, T3, T4, T5, T6, T7>(Action<T1, T2, T3, T4, T5, T6, T7> action)
{
var service1 = GetOrInstantiate<T1>();
var service2 = GetOrInstantiate<T2>();
var service3 = GetOrInstantiate<T3>();
var service4 = GetOrInstantiate<T4>();
var service5 = GetOrInstantiate<T5>();
var service6 = GetOrInstantiate<T6>();
var service7 = GetOrInstantiate<T7>();
action(service1, service2, service3, service4, service5, service6, service7);
return this;
}
public ISereinIoc Run<T1, T2, T3, T4, T5, T6, T7, T8>(Action<T1, T2, T3, T4, T5, T6, T7, T8> action)
{
var service1 = GetOrInstantiate<T1>();
var service2 = GetOrInstantiate<T2>();
var service3 = GetOrInstantiate<T3>();
var service4 = GetOrInstantiate<T4>();
var service5 = GetOrInstantiate<T5>();
var service6 = GetOrInstantiate<T6>();
var service7 = GetOrInstantiate<T7>();
var service8 = GetOrInstantiate<T8>();
action(service1, service2, service3, service4, service5, service6, service7, service8);
return this;
}
#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);
}
}
}*/
}