ioc

public class Ioc : IServiceProvider
{
private Ioc _root;
private ConcurrentDictionary<Type, ServiceRegistry> _registries = new ConcurrentDictionary<Type, ServiceRegistry>();
private ConcurrentDictionary<Type, object?> _services = new ConcurrentDictionary<Type, object?>();

public Ioc()
{
this._root = this;
}

public Ioc(Ioc parent)
{
this._root = parent._root;
this._services = parent._services;
}

public Ioc CreateScope()
{
return new Ioc(this);
}

public Ioc Register(ServiceRegistry serviceRegistry)
{
if (_registries.TryGetValue(serviceRegistry.ServiceType, out var exist))
{
serviceRegistry.Next = exist;
}

_registries[serviceRegistry.ServiceType] = serviceRegistry;

return this;
}

public bool HasRegistry(Type serviceType)
{
return _services.ContainsKey(serviceType);
}

public object? GetService(Type serviceType)
{
// ioc 直接返回自己
if (serviceType == typeof(Ioc) || serviceType == typeof(IServiceProvider))
{
return this;
}

ServiceRegistry? registry;

// 服务类型为IEnumerable
if (serviceType.IsGenericType && serviceType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
{
// 未注册,返回空数组
var elementType = serviceType.GetGenericArguments()[0];
if (!_registries.TryGetValue(elementType, out registry))
{
return Array.CreateInstance(elementType, 0);
}

// 已注册,则从容器中获取所有实例
var registries = registry.AsEnumerable();
var services = registries.Select(it => GetServiceCore(it, new Type[0])).ToArray();
Array array = Array.CreateInstance(elementType, services.Length);
services.CopyTo(array, 0);
return array;
}

// 泛型
if (serviceType.IsGenericType && !_registries.ContainsKey(serviceType))
{
var definition = serviceType.GetGenericTypeDefinition();
return _registries.TryGetValue(definition, out registry)
? GetServiceCore(registry, serviceType.GetGenericArguments())
: null;
}

// 默认
return _registries.TryGetValue(serviceType, out registry)
? GetServiceCore(registry, new Type[0])
: null;
}

private object? GetServiceCore(ServiceRegistry serviceRegistry, Type[] genericArguments)
{
switch (serviceRegistry.LifeTime)
{
case LifeTime.Scope:
return GetOrCreate(serviceRegistry, genericArguments);
case LifeTime.Singleton:
return _root.GetOrCreate(serviceRegistry, genericArguments);
default:
return serviceRegistry.Factory(this, genericArguments);
}
}

private object? GetOrCreate(ServiceRegistry serviceRegistry, Type[] genericArguments)
{
if (_services.TryGetValue(serviceRegistry.ServiceType, out var service))
{
return service;
}

var instance = serviceRegistry.Factory(this, genericArguments);
_services.TryAdd(serviceRegistry.ServiceType, instance);
return instance;
}
}

public static class IocExtensions
{
public static Ioc Register(this Ioc ioc, Type serviceType, Type implType, LifeTime lifetime)
{
Func<Ioc, Type[], object?> factory = (, arguments) => Create(, implType, arguments);
ioc.Register(new ServiceRegistry(serviceType, lifetime, factory));
return ioc;
}

public static Ioc Register<TFrom, TTo>(this Ioc ioc, LifeTime lifetime) where TTo : TFrom
=> ioc.Register(typeof(TFrom), typeof(TTo), lifetime);

public static Ioc Register(this Ioc ioc, TServiceType instance)
{
Func<Ioc, Type[], object?> factory = (_, arguments) => instance;
ioc.Register(new ServiceRegistry(typeof(TServiceType), LifeTime.Singleton, factory));
return ioc;
}

public static Ioc Register(this Ioc ioc, Func<Ioc, TServiceType> factory, LifeTime lifetime)
{
ioc.Register(new ServiceRegistry(typeof(TServiceType), lifetime, (, arguments) => factory()));
return ioc;
}

private static object? Create(Ioc ico, Type type, Type[] genericArguments)
{
// 闭合泛型
if (genericArguments.Length > 0)
{
type = type.MakeGenericType(genericArguments);
}

// 查找构造函数
var constructors = type.GetConstructors(BindingFlags.Instance);
if (constructors.Length == 0)
{
throw new InvalidOperationException($"Cannot create the instance of {type} which does not have an public constructor.");
}
var constructor = constructors.FirstOrDefault(it => it.GetCustomAttributes(false).OfType().Any());
constructor = constructor ?? constructors.First();

// 构造函数参数为空,直接new
var parameters = constructor.GetParameters();
if (parameters.Length == 0)
{
return Activator.CreateInstance(type);
}

// 生成实参
var arguments = new object?[parameters.Length];
for (int index = 0; index < arguments.Length; index++)
{
var parameter = parameters[index];
var parameterType = parameter.ParameterType;
if (ico.HasRegistry(parameterType))
{
arguments[index] = ico.GetService(parameterType);
}
else if (parameter.HasDefaultValue)
{
arguments[index] = parameter.DefaultValue;
}
else
{
throw new InvalidOperationException($"Cannot create the instance of {type} whose constructor has non-registered parameter type(s)");
}
}

return Activator.CreateInstance(type, arguments);
}
}

public class ServiceRegistry
{
public Type ServiceType { get; set; }
public LifeTime LifeTime { get; set; }
public Func<Ioc, Type[], object?> Factory { get; set; }
public ServiceRegistry? Next { get; set; }

public ServiceRegistry(Type serviceType, LifeTime lifetime, Func<Ioc, Type[], object?> factory)
{
ServiceType = serviceType;
LifeTime = lifetime;
Factory = factory;
}

internal IEnumerable AsEnumerable()
{
var list = new List();
for (var self = this; self != null; self = self.Next)
{
list.Add(self);
}
return list;
}
}

public enum LifeTime
{
Transient,
Scope,
Singleton
}

[AttributeUsage(AttributeTargets.Constructor)]
public class InjectionAttribute : Attribute { }

来自: https://www.cnblogs.com/artech/p/net-core-di-05.html

posted @ 2024-09-04 11:54  pojianbing  阅读(49)  评论(0)    收藏  举报