Intro# 在上一篇文章中主要介绍了一下要做的依赖注入的整体设计和大概编程体验,这篇文章要开始写代码了,开始实现自己的依赖注入框架。 类图# 首先来温习一下上次提到的类图 服务生命周期# 服务生命周期定义: Copy public enum ServiceLifetime : sbyte { /// /// Specifies that a single instance of the service will be created. /// Singleton = 0, /// /// Specifies that a new instance of the service will be created for each scope. /// Scoped = 1, /// /// Specifies that a new instance of the service will be created every time it is requested. /// Transient = 2, } 服务定义# 服务注册定义: Copy public class ServiceDefinition { // 服务生命周期 public ServiceLifetime ServiceLifetime { get; } // 实现类型 public Type ImplementType { get; } // 服务类型 public Type ServiceType { get; } // 实现实例 public object ImplementationInstance { get; } // 实现工厂 public Func 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 factory, ServiceLifetime serviceLifetime) { ServiceType = serviceType; ImplementationFactory = factory; ServiceLifetime = serviceLifetime; } } 为了使用起来更方便添加了一些静态方法 Copy public static ServiceDefinition Singleton(Func factory) { return new ServiceDefinition(typeof(TService), factory, ServiceLifetime.Singleton); } public static ServiceDefinition Scoped(Func factory) { return new ServiceDefinition(typeof(TService), factory, ServiceLifetime.Scoped); } public static ServiceDefinition Transient(Func factory) { return new ServiceDefinition(typeof(TService), factory, ServiceLifetime.Transient); } public static ServiceDefinition Singleton() { return new ServiceDefinition(typeof(TService), ServiceLifetime.Singleton); } public static ServiceDefinition Scoped() { return new ServiceDefinition(typeof(TService), ServiceLifetime.Scoped); } public static ServiceDefinition Transient() { return new ServiceDefinition(typeof(TService), ServiceLifetime.Transient); } public static ServiceDefinition Singleton() where TServiceImplement : TService { return new ServiceDefinition(typeof(TService), typeof(TServiceImplement), ServiceLifetime.Singleton); } public static ServiceDefinition Scoped() where TServiceImplement : TService { return new ServiceDefinition(typeof(TService), typeof(TServiceImplement), ServiceLifetime.Scoped); } public static ServiceDefinition Transient() where TServiceImplement : TService { return new ServiceDefinition(typeof(TService), typeof(TServiceImplement), ServiceLifetime.Transient); } ServiceContainer# serviceContainer v1# Copy public class ServiceContainer : IServiceContainer { internal readonly List _services; private readonly ConcurrentDictionary _singletonInstances; private readonly ConcurrentDictionary _scopedInstances; private readonly List _transientDisposables = new List(); private readonly bool _isRootScope; public ServiceContainer() { _isRootScope = true; _singletonInstances = new ConcurrentDictionary(); _services = new List(); } internal ServiceContainer(ServiceContainer serviceContainer) { _isRootScope = false; _singletonInstances = serviceContainer._singletonInstances; _services = serviceContainer._services; _scopedInstances = new ConcurrentDictionary(); } 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>(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>(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; } } } 为了使得服务注册更加方便,可以写一些扩展方法来方便注册: Copy public static IServiceContainer AddSingleton([NotNull]this IServiceContainer serviceContainer, [NotNull]TService service) { serviceContainer.Add(new ServiceDefinition(service, typeof(TService))); return serviceContainer; } public static IServiceContainer AddSingleton([NotNull]this IServiceContainer serviceContainer, [NotNull]Type serviceType) { serviceContainer.Add(new ServiceDefinition(serviceType, ServiceLifetime.Singleton)); return serviceContainer; } public static IServiceContainer AddSingleton([NotNull]this IServiceContainer serviceContainer, [NotNull]Type serviceType, [NotNull]Type implementType) { serviceContainer.Add(new ServiceDefinition(serviceType, implementType, ServiceLifetime.Singleton)); return serviceContainer; } public static IServiceContainer AddSingleton([NotNull]this IServiceContainer serviceContainer, [NotNull]Func func) { serviceContainer.Add(ServiceDefinition.Singleton(func)); return serviceContainer; } public static IServiceContainer AddSingleton([NotNull]this IServiceContainer serviceContainer) { serviceContainer.Add(ServiceDefinition.Singleton()); return serviceContainer; } public static IServiceContainer AddSingleton([NotNull]this IServiceContainer serviceContainer) where TServiceImplement : TService { serviceContainer.Add(ServiceDefinition.Singleton()); return serviceContainer; } public static IServiceContainer AddScoped([NotNull]this IServiceContainer serviceContainer, [NotNull]Type serviceType) { serviceContainer.Add(new ServiceDefinition(serviceType, ServiceLifetime.Scoped)); return serviceContainer; } public static IServiceContainer AddScoped([NotNull]this IServiceContainer serviceContainer, [NotNull]Type serviceType, [NotNull]Type implementType) { serviceContainer.Add(new ServiceDefinition(serviceType, implementType, ServiceLifetime.Scoped)); return serviceContainer; } public static IServiceContainer AddScoped([NotNull]this IServiceContainer serviceContainer, [NotNull]Func func) { serviceContainer.Add(ServiceDefinition.Scoped(func)); return serviceContainer; } public static IServiceContainer AddScoped([NotNull]this IServiceContainer serviceContainer) { serviceContainer.Add(ServiceDefinition.Scoped()); return serviceContainer; } public static IServiceContainer AddScoped([NotNull]this IServiceContainer serviceContainer) where TServiceImplement : TService { serviceContainer.Add(ServiceDefinition.Scoped()); return serviceContainer; } public static IServiceContainer AddTransient([NotNull]this IServiceContainer serviceContainer, [NotNull]Type serviceType) { serviceContainer.Add(new ServiceDefinition(serviceType, ServiceLifetime.Transient)); return serviceContainer; } public static IServiceContainer AddTransient([NotNull]this IServiceContainer serviceContainer, [NotNull]Type serviceType, [NotNull]Type implementType) { serviceContainer.Add(new ServiceDefinition(serviceType, implementType, ServiceLifetime.Transient)); return serviceContainer; } public static IServiceContainer AddTransient([NotNull]this IServiceContainer serviceContainer, [NotNull]Func func) { serviceContainer.Add(ServiceDefinition.Transient(func)); return serviceContainer; } public static IServiceContainer AddTransient([NotNull]this IServiceContainer serviceContainer) { serviceContainer.Add(ServiceDefinition.Transient()); return serviceContainer; } public static IServiceContainer AddTransient([NotNull]this IServiceContainer serviceContainer) where TServiceImplement : TService { serviceContainer.Add(ServiceDefinition.Transient