动手造轮子:实现一个简单的依赖注入(一)

动手造轮子:实现一个简单的依赖注入(一) Intro

在上一篇文章中主要介绍了一下要做的依赖注入的整体设计和大概编程体验,这篇文章要开始写代码了,开始实现自己的依赖注入框架。

类图

首先来温习一下上次提到的类图

动手造轮子:实现一个简单的依赖注入(一)

服务生命周期

服务生命周期定义:

public enum ServiceLifetime : sbyte { /// <summary> /// Specifies that a single instance of the service will be created. /// </summary> Singleton = 0, /// <summary> /// Specifies that a new instance of the service will be created for each scope. /// </summary> Scoped = 1, /// <summary> /// Specifies that a new instance of the service will be created every time it is requested. /// </summary> Transient = 2, } 服务定义

服务注册定义:

public class ServiceDefinition { // 服务生命周期 public ServiceLifetime ServiceLifetime { get; } // 实现类型 public Type ImplementType { get; } // 服务类型 public Type ServiceType { get; } // 实现实例 public object ImplementationInstance { get; } // 实现工厂 public Func<IServiceProvider, object> ImplementationFactory { get; } // 获取真实的实现类型 public Type GetImplementType() { if (ImplementationInstance != null) return ImplementationInstance.GetType(); if (ImplementationFactory != null) return ImplementationFactory.Method.DeclaringType; if (ImplementType != null) return ImplementType; return ServiceType; } public ServiceDefinition(object instance, Type serviceType) { ImplementationInstance = instance; ServiceType = serviceType; ServiceLifetime = ServiceLifetime.Singleton; } public ServiceDefinition(Type serviceType, ServiceLifetime serviceLifetime) : this(serviceType, serviceType, serviceLifetime) { } public ServiceDefinition(Type serviceType, Type implementType, ServiceLifetime serviceLifetime) { ServiceType = serviceType; ImplementType = implementType ?? serviceType; ServiceLifetime = serviceLifetime; } public ServiceDefinition(Type serviceType, Func<IServiceProvider, object> factory, ServiceLifetime serviceLifetime) { ServiceType = serviceType; ImplementationFactory = factory; ServiceLifetime = serviceLifetime; } }

为了使用起来更方便添加了一些静态方法

public static ServiceDefinition Singleton<TService>(Func<IServiceProvider, object> factory) { return new ServiceDefinition(typeof(TService), factory, ServiceLifetime.Singleton); } public static ServiceDefinition Scoped<TService>(Func<IServiceProvider, object> factory) { return new ServiceDefinition(typeof(TService), factory, ServiceLifetime.Scoped); } public static ServiceDefinition Transient<TService>(Func<IServiceProvider, object> factory) { return new ServiceDefinition(typeof(TService), factory, ServiceLifetime.Transient); } public static ServiceDefinition Singleton<TService>() { return new ServiceDefinition(typeof(TService), ServiceLifetime.Singleton); } public static ServiceDefinition Scoped<TService>() { return new ServiceDefinition(typeof(TService), ServiceLifetime.Scoped); } public static ServiceDefinition Transient<TService>() { return new ServiceDefinition(typeof(TService), ServiceLifetime.Transient); } public static ServiceDefinition Singleton<TService, TServiceImplement>() where TServiceImplement : TService { return new ServiceDefinition(typeof(TService), typeof(TServiceImplement), ServiceLifetime.Singleton); } public static ServiceDefinition Scoped<TService, TServiceImplement>() where TServiceImplement : TService { return new ServiceDefinition(typeof(TService), typeof(TServiceImplement), ServiceLifetime.Scoped); } public static ServiceDefinition Transient<TService, TServiceImplement>() where TServiceImplement : TService { return new ServiceDefinition(typeof(TService), typeof(TServiceImplement), ServiceLifetime.Transient); } ServiceContainer serviceContainer v1 public class ServiceContainer : IServiceContainer { internal readonly List<ServiceDefinition> _services; private readonly ConcurrentDictionary<Type, object> _singletonInstances; private readonly ConcurrentDictionary<Type, object> _scopedInstances; private readonly List<object> _transientDisposables = new List<object>(); private readonly bool _isRootScope; public ServiceContainer() { _isRootScope = true; _singletonInstances = new ConcurrentDictionary<Type, object>(); _services = new List<ServiceDefinition>(); } internal ServiceContainer(ServiceContainer serviceContainer) { _isRootScope = false; _singletonInstances = serviceContainer._singletonInstances; _services = serviceContainer._services; _scopedInstances = new ConcurrentDictionary<Type, object>(); } public void Add(ServiceDefinition item) { _services.Add(item); } public IServiceContainer CreateScope() { return new ServiceContainer(this); } private bool _disposed; public void Dispose() { if (_disposed) { return; } if (_isRootScope) { lock (_singletonInstances) { if (_disposed) { return; } _disposed = true; foreach (var instance in _singletonInstances.Values) { (instance as IDisposable)?.Dispose(); } foreach (var o in _transientDisposables) { (o as IDisposable)?.Dispose(); } } } else { lock (_scopedInstances) { if (_disposed) { return; } _disposed = true; foreach (var instance in _scopedInstances.Values) { (instance as IDisposable)?.Dispose(); } foreach (var o in _transientDisposables) { (o as IDisposable)?.Dispose(); } } } } private object GetServiceInstance(Type serviceType, ServiceDefinition serviceDefinition) { if (serviceDefinition.ImplementationInstance != null) return serviceDefinition.ImplementationInstance; if (serviceDefinition.ImplementationFactory != null) return serviceDefinition.ImplementationFactory.Invoke(this); var implementType = (serviceDefinition.ImplementType ?? serviceType); if (implementType.IsInterface || implementType.IsAbstract) { throw new InvalidOperationException($"invalid service registered, serviceType: {serviceType.FullName}, implementType: {serviceDefinition.ImplementType}"); } var ctorInfos = implementType.GetConstructors(BindingFlags.Instance | BindingFlags.Public); if (ctorInfos.Length == 0) { throw new InvalidOperationException($"service {serviceType.FullName} does not have any public constructors"); } ConstructorInfo ctor; if (ctorInfos.Length == 1) { ctor = ctorInfos[0]; } else { // try find best ctor ctor = ctorInfos .OrderBy(_ => _.GetParameters().Length) .First(); } var parameters = ctor.GetParameters(); if (parameters.Length == 0) { // TODO: cache New Func return Expression.Lambda<Func<object>>(Expression.New(ctor)).Compile().Invoke(); } else { var ctorParams = new object[parameters.Length]; for (var index = 0; index < parameters.Length; index++) { var parameter = parameters[index]; var param = GetService(parameter.ParameterType); if (param == null && parameter.HasDefaultValue) { param = parameter.DefaultValue; } ctorParams[index] = param; } return Expression.Lambda<Func<object>>(Expression.New(ctor, ctorParams.Select(Expression.Constant))).Compile().Invoke(); } } public object GetService(Type serviceType) { var serviceDefinition = _services.LastOrDefault(_ => _.ServiceType == serviceType); if (null == serviceDefinition) { return null; } if (_isRootScope && serviceDefinition.ServiceLifetime == ServiceLifetime.Scoped) { throw new InvalidOperationException($"can not get scope service from the root scope, serviceType: {serviceType.FullName}"); } if (serviceDefinition.ServiceLifetime == ServiceLifetime.Singleton) { var svc = _singletonInstances.GetOrAdd(serviceType, (t) => GetServiceInstance(t, serviceDefinition)); return svc; } else if (serviceDefinition.ServiceLifetime == ServiceLifetime.Scoped) { var svc = _scopedInstances.GetOrAdd(serviceType, (t) => GetServiceInstance(t, serviceDefinition)); return svc; } else { var svc = GetServiceInstance(serviceType, serviceDefinition); if (svc is IDisposable) { _transientDisposables.Add(svc); } return svc; } } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzypyz.html