//------------------------------------------------------------------------------
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
// CSDN博客:https://blog.csdn.net/qq_40374647
// 哔哩哔哩视频:https://space.bilibili.com/94253567
// Gitee源代码仓库:https://gitee.com/RRQM_Home
// Github源代码仓库:https://github.com/RRQM
// API首页:https://www.yuque.com/rrqm/touchsocket/index
// 交流QQ群:234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace TouchSocket.Core
{
///
/// IOC容器
///
public class Container : IContainer
{
private readonly ConcurrentDictionary m_registrations = new ConcurrentDictionary();
///
/// 初始化一个IOC容器
///
public Container()
{
this.RegisterSingleton(this);
}
///
/// 返回迭代器
///
///
public IEnumerator GetEnumerator()
{
return m_registrations.Values.ToList().GetEnumerator();
}
///
///
///
///
///
///
public bool IsRegistered(Type fromType, string key = "")
{
return m_registrations.ContainsKey($"{fromType.FullName}{key}");
}
///
///
///
///
///
public void Register(DependencyDescriptor descriptor, string key = "")
{
string k = $"{descriptor.FromType.FullName}{key}";
m_registrations.AddOrUpdate(k, descriptor, (k, v) => { return descriptor; });
}
///
///
///
///
///
///
///
public object Resolve(Type fromType, object[] ps = null, string key = "")
{
if (fromType == typeof(IContainerProvider))
{
return GetScopedContainer();
}
string k;
DependencyDescriptor descriptor;
if (fromType.IsGenericType)
{
Type type = fromType.GetGenericTypeDefinition();
k = $"{type.FullName}{key}";
if (m_registrations.TryGetValue(k, out descriptor))
{
if (descriptor.ImplementationFactory != null)
{
return descriptor.ImplementationFactory.Invoke(this);
}
if (descriptor.Lifetime == Lifetime.Singleton)
{
if (descriptor.ToInstance != null)
{
return descriptor.ToInstance;
}
lock (descriptor)
{
if (descriptor.ToInstance != null)
{
return descriptor.ToInstance;
}
if (descriptor.ToType.IsGenericType)
{
return descriptor.ToInstance = Create(descriptor.ToType.MakeGenericType(fromType.GetGenericArguments()), ps);
}
else
{
return descriptor.ToInstance = Create(descriptor.ToType, ps);
}
}
}
if (descriptor.ToType.IsGenericType)
{
return Create(descriptor.ToType.MakeGenericType(fromType.GetGenericArguments()), ps);
}
else
{
return Create(descriptor.ToType, ps);
}
}
}
k = $"{fromType.FullName}{key}";
if (m_registrations.TryGetValue(k, out descriptor))
{
if (descriptor.ImplementationFactory != null)
{
return descriptor.ImplementationFactory.Invoke(this);
}
if (descriptor.Lifetime == Lifetime.Singleton)
{
if (descriptor.ToInstance != null)
{
return descriptor.ToInstance;
}
lock (descriptor)
{
if (descriptor.ToInstance != null)
{
return descriptor.ToInstance;
}
return descriptor.ToInstance = Create(descriptor.ToType, ps);
}
}
return Create(descriptor.ToType, ps);
}
else if (fromType.IsPrimitive || fromType == typeof(string))
{
return default;
}
else if (fromType.IsClass && !fromType.IsAbstract)
{
if (fromType.GetCustomAttribute() is DependencyInjectAttribute attribute)
{
if (attribute.ResolveNullIfNoRegistered && !IsRegistered(fromType, key))
{
return default;
}
}
return Create(fromType, ps);
}
else
{
return default;
}
}
///
///
///
///
///
public void Unregister(DependencyDescriptor descriptor, string key = "")
{
string k = $"{descriptor.FromType.FullName}{key}";
m_registrations.TryRemove(k, out _);
}
///
///
///
///
///
///
private object Create(Type toType, object[] ops)
{
ConstructorInfo ctor = toType.GetConstructors().FirstOrDefault(x => x.IsDefined(typeof(DependencyInjectAttribute), true));
if (ctor is null)
{
//如果没有被特性标记,那就取构造函数参数最多的作为注入目标
if (toType.GetConstructors().Length == 0)
{
throw new Exception($"没有找到类型{toType.FullName}的公共构造函数。");
}
ctor = toType.GetConstructors().OrderByDescending(x => x.GetParameters().Length).First();
}
else
{
if (ops == null)
{
ops = ctor.GetCustomAttribute().Ps;
}
}
DependencyTypeAttribute dependencyTypeAttribute = null;
if (toType.IsDefined(typeof(DependencyTypeAttribute), true))
{
dependencyTypeAttribute = toType.GetCustomAttribute();
}
var parameters = ctor.GetParameters();
object[] ps = new object[parameters.Length];
if (dependencyTypeAttribute == null || dependencyTypeAttribute.Type.HasFlag(DependencyType.Constructor))
{
for (int i = 0; i < parameters.Length; i++)
{
if (ops != null && ops.Length - 1 >= i)
{
ps[i] = ops[i];
}
else
{
if (parameters[i].ParameterType.IsPrimitive || parameters[i].ParameterType == typeof(string))
{
if (parameters[i].HasDefaultValue)
{
ps[i] = parameters[i].DefaultValue;
}
else
{
ps[i] = default;
}
}
else
{
if (parameters[i].IsDefined(typeof(DependencyParamterInjectAttribute), true))
{
DependencyParamterInjectAttribute attribute = parameters[i].GetCustomAttribute();
Type type = attribute.Type == null ? parameters[i].ParameterType : attribute.Type;
if (attribute.ResolveNullIfNoRegistered && !IsRegistered(type, attribute.Key))
{
ps[i] = default;
}
else
{
ps[i] = Resolve(type, attribute.Ps, attribute.Key);
}
}
else
{
ps[i] = Resolve(parameters[i].ParameterType, null);
}
}
}
}
}
object instance = Activator.CreateInstance(toType, ps);
if (dependencyTypeAttribute == null || dependencyTypeAttribute.Type.HasFlag(DependencyType.Property))
{
var propetys = toType.GetProperties().Where(x => x.IsDefined(typeof(DependencyInjectAttribute), true));
foreach (var item in propetys)
{
if (item.CanWrite)
{
object obj;
if (item.IsDefined(typeof(DependencyParamterInjectAttribute), true))
{
DependencyParamterInjectAttribute attribute = item.GetCustomAttribute();
Type type = attribute.Type == null ? item.PropertyType : attribute.Type;
if (attribute.ResolveNullIfNoRegistered && !IsRegistered(type, attribute.Key))
{
obj = null;
}
else
{
obj = Resolve(type, attribute.Ps, attribute.Key);
}
}
else
{
obj = Resolve(item.PropertyType, null);
}
item.SetValue(instance, obj);
}
}
}
if (dependencyTypeAttribute == null || dependencyTypeAttribute.Type.HasFlag(DependencyType.Method))
{
var methods = toType.GetMethods( BindingFlags.Default| BindingFlags.Instance| BindingFlags.Static| BindingFlags.Public| BindingFlags.NonPublic).Where(x => x.IsDefined(typeof(DependencyInjectAttribute), true)).ToList();
foreach (var item in methods)
{
parameters = item.GetParameters();
ops = item.GetCustomAttribute().Ps;
ps = new object[parameters.Length];
for (int i = 0; i < ps.Length; i++)
{
if (ops != null && ops.Length - 1 >= i)
{
ps[i] = ops[i];
}
else
{
if (parameters[i].ParameterType.IsPrimitive || parameters[i].ParameterType == typeof(string))
{
if (parameters[i].HasDefaultValue)
{
ps[i] = parameters[i].DefaultValue;
}
else
{
ps[i] = default;
}
}
else
{
if (parameters[i].IsDefined(typeof(DependencyParamterInjectAttribute), true))
{
DependencyParamterInjectAttribute attribute = parameters[i].GetCustomAttribute();
Type type = attribute.Type == null ? parameters[i].ParameterType : attribute.Type;
if (attribute.ResolveNullIfNoRegistered && !IsRegistered(type, attribute.Key))
{
ps[i] = default;
}
else
{
ps[i] = Resolve(type, attribute.Ps, attribute.Key);
}
}
else
{
ps[i] = Resolve(parameters[i].ParameterType, null);
}
}
}
}
item.Invoke(instance, ps);
}
}
return instance;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
private IContainerProvider GetScopedContainer()
{
Container container = new Container();
foreach (var item in m_registrations)
{
if (item.Value.Lifetime == Lifetime.Scoped)
{
container.m_registrations.AddOrUpdate(item.Key, new DependencyDescriptor(item.Value.FromType, item.Value.ToType, Lifetime.Singleton), (k, v) => { return v; });
}
else
{
container.m_registrations.AddOrUpdate(item.Key, item.Value, (k, v) => { return v; });
}
}
return new ContainerProvider(container);
}
}
}