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<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

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