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<T>
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<TServiceType>(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<TServiceType>(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<InjectionAttribute>().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<ServiceRegistry> AsEnumerable()
{
var list = new List<ServiceRegistry>();
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