nuget包:在以Microsoft.Extensins.DependencyInjection开头的包中,直接引入对应的nuget包。
github地址:https://github.com/dotnet/extensions/tree/master/src/DependencyInjection
先看下这几个接口
ServiceDescriptor类:
该类是服务和其实现的描述,是整个依赖注入的基石
[DebuggerDisplay("Lifetime = {Lifetime}, ServiceType = {ServiceType}, ImplementationType = {ImplementationType}")] public class ServiceDescriptor { /// <summary> /// Initializes a new instance of <see cref="ServiceDescriptor"/> with the specified <paramref name="implementationType"/>. /// </summary> /// <param name="serviceType">The <see cref="Type"/> of the service.</param> /// <param name="implementationType">The <see cref="Type"/> implementing the service.</param> /// <param name="lifetime">The <see cref="ServiceLifetime"/> of the service.</param> public ServiceDescriptor( Type serviceType, Type implementationType, ServiceLifetime lifetime) : this(serviceType, lifetime) { if (serviceType == null) { throw new ArgumentNullException(nameof(serviceType)); } if (implementationType == null) { throw new ArgumentNullException(nameof(implementationType)); } ImplementationType = implementationType; } /// <summary> /// Initializes a new instance of <see cref="ServiceDescriptor"/> with the specified <paramref name="instance"/> /// as a <see cref="ServiceLifetime.Singleton"/>. /// </summary> /// <param name="serviceType">The <see cref="Type"/> of the service.</param> /// <param name="instance">The instance implementing the service.</param> public ServiceDescriptor(Type serviceType, object instance) : this(serviceType, ServiceLifetime.Singleton) { if (serviceType == null) { throw new ArgumentNullException(nameof(serviceType)); } if (instance == null) { throw new ArgumentNullException(nameof(instance)); } ImplementationInstance = instance; } /// <summary> /// Initializes a new instance of <see cref="ServiceDescriptor"/> with the specified <paramref name="factory"/>. /// </summary> /// <param name="serviceType">The <see cref="Type"/> of the service.</param> /// <param name="factory">A factory used for creating service instances.</param> /// <param name="lifetime">The <see cref="ServiceLifetime"/> of the service.</param> public ServiceDescriptor(Type serviceType, Func<IServiceProvider, object> factory, ServiceLifetime lifetime) : this(serviceType, lifetime) { if (serviceType == null) { throw new ArgumentNullException(nameof(serviceType)); } if (factory == null) { throw new ArgumentNullException(nameof(factory)); } ImplementationFactory = factory; } private ServiceDescriptor(Type serviceType, ServiceLifetime lifetime) { Lifetime = lifetime; ServiceType = serviceType; } /// <inheritdoc /> public ServiceLifetime Lifetime { get; } /// <inheritdoc /> public Type ServiceType { get; } /// <inheritdoc /> public Type ImplementationType { get; } /// <inheritdoc /> public object ImplementationInstance { get; } /// <inheritdoc /> public Func<IServiceProvider, object> ImplementationFactory { get; } /// <inheritdoc /> public override string ToString() { var lifetime = $"{nameof(ServiceType)}: {ServiceType} {nameof(Lifetime)}: {Lifetime} "; if (ImplementationType != null) { return lifetime + $"{nameof(ImplementationType)}: {ImplementationType}"; } if (ImplementationFactory != null) { return lifetime + $"{nameof(ImplementationFactory)}: {ImplementationFactory.Method}"; } return lifetime + $"{nameof(ImplementationInstance)}: {ImplementationInstance}"; } internal Type GetImplementationType() { if (ImplementationType != null) { return ImplementationType; } else if (ImplementationInstance != null) { return ImplementationInstance.GetType(); } else if (ImplementationFactory != null) { var typeArguments = ImplementationFactory.GetType().GenericTypeArguments; Debug.Assert(typeArguments.Length == 2); return typeArguments[1]; } Debug.Assert(false, "ImplementationType, ImplementationInstance or ImplementationFactory must be non null"); return null; } /// <summary> /// Creates an instance of <see cref="ServiceDescriptor"/> with the specified /// <typeparamref name="TService"/>, <typeparamref name="TImplementation"/>, /// and the <see cref="ServiceLifetime.Transient"/> lifetime. /// </summary> /// <typeparam name="TService">The type of the service.</typeparam> /// <typeparam name="TImplementation">The type of the implementation.</typeparam> /// <returns>A new instance of <see cref="ServiceDescriptor"/>.</returns> public static ServiceDescriptor Transient<TService, TImplementation>() where TService : class where TImplementation : class, TService { return Describe<TService, TImplementation>(ServiceLifetime.Transient); } /// <summary> /// Creates an instance of <see cref="ServiceDescriptor"/> with the specified /// <paramref name="service"/> and <paramref name="implementationType"/> /// and the <see cref="ServiceLifetime.Transient"/> lifetime. /// </summary> /// <param name="service">The type of the service.</param> /// <param name="implementationType">The type of the implementation.</param> /// <returns>A new instance of <see cref="ServiceDescriptor"/>.</returns> public static ServiceDescriptor Transient(Type service, Type implementationType) { if (service == null) { throw new ArgumentNullException(nameof(service)); } if (implementationType == null) { throw new ArgumentNullException(nameof(implementationType)); } return Describe(service, implementationType, ServiceLifetime.Transient); } /// <summary> /// Creates an instance of <see cref="ServiceDescriptor"/> with the specified /// <typeparamref name="TService"/>, <typeparamref name="TImplementation"/>, /// <paramref name="implementationFactory"/>, /// and the <see cref="ServiceLifetime.Transient"/> lifetime. /// </summary> /// <typeparam name="TService">The type of the service.</typeparam> /// <typeparam name="TImplementation">The type of the implementation.</typeparam> /// <param name="implementationFactory">A factory to create new instances of the service implementation.</param> /// <returns>A new instance of <see cref="ServiceDescriptor"/>.</returns> public static ServiceDescriptor Transient<TService, TImplementation>( Func<IServiceProvider, TImplementation> implementationFactory) where TService : class where TImplementation : class, TService { if (implementationFactory == null) { throw new ArgumentNullException(nameof(implementationFactory)); } return Describe(typeof(TService), implementationFactory, ServiceLifetime.Transient); } /// <summary> /// Creates an instance of <see cref="ServiceDescriptor"/> with the specified /// <typeparamref name="TService"/>, <paramref name="implementationFactory"/>, /// and the <see cref="ServiceLifetime.Transient"/> lifetime. /// </summary> /// <typeparam name="TService">The type of the service.</typeparam> /// <param name="implementationFactory">A factory to create new instances of the service implementation.</param> /// <returns>A new instance of <see cref="ServiceDescriptor"/>.</returns> public static ServiceDescriptor Transient<TService>(Func<IServiceProvider, TService> implementationFactory) where TService : class { if (implementationFactory == null) { throw new ArgumentNullException(nameof(implementationFactory)); } return Describe(typeof(TService), implementationFactory, ServiceLifetime.Transient); } /// <summary> /// Creates an instance of <see cref="ServiceDescriptor"/> with the specified /// <paramref name="service"/>, <paramref name="implementationFactory"/>, /// and the <see cref="ServiceLifetime.Transient"/> lifetime. /// </summary> /// <param name="service">The type of the service.</param> /// <param name="implementationFactory">A factory to create new instances of the service implementation.</param> /// <returns>A new instance of <see cref="ServiceDescriptor"/>.</returns> public static ServiceDescriptor Transient(Type service, Func<IServiceProvider, object> implementationFactory) { if (service == null) { throw new ArgumentNullException(nameof(service)); } if (implementationFactory == null) { throw new ArgumentNullException(nameof(implementationFactory)); } return Describe(service, implementationFactory, ServiceLifetime.Transient); } /// <summary> /// Creates an instance of <see cref="ServiceDescriptor"/> with the specified /// <typeparamref name="TService"/>, <typeparamref name="TImplementation"/>, /// and the <see cref="ServiceLifetime.Scoped"/> lifetime. /// </summary> /// <typeparam name="TService">The type of the service.</typeparam> /// <typeparam name="TImplementation">The type of the implementation.</typeparam> /// <returns>A new instance of <see cref="ServiceDescriptor"/>.</returns> public static ServiceDescriptor Scoped<TService, TImplementation>() where TService : class where TImplementation : class, TService { return Describe<TService, TImplementation>(ServiceLifetime.Scoped); } /// <summary> /// Creates an instance of <see cref="ServiceDescriptor"/> with the specified /// <paramref name="service"/> and <paramref name="implementationType"/> /// and the <see cref="ServiceLifetime.Scoped"/> lifetime. /// </summary> /// <param name="service">The type of the service.</param> /// <param name="implementationType">The type of the implementation.</param> /// <returns>A new instance of <see cref="ServiceDescriptor"/>.</returns> public static ServiceDescriptor Scoped(Type service, Type implementationType) { return Describe(service, implementationType, ServiceLifetime.Scoped); } /// <summary> /// Creates an instance of <see cref="ServiceDescriptor"/> with the specified /// <typeparamref name="TService"/>, <typeparamref name="TImplementation"/>, /// <paramref name="implementationFactory"/>, /// and the <see cref="ServiceLifetime.Scoped"/> lifetime. /// </summary> /// <typeparam name="TService">The type of the service.</typeparam> /// <typeparam name="TImplementation">The type of the implementation.</typeparam> /// <param name="implementationFactory">A factory to create new instances of the service implementation.</param> /// <returns>A new instance of <see cref="ServiceDescriptor"/>.</returns> public static ServiceDescriptor Scoped<TService, TImplementation>( Func<IServiceProvider, TImplementation> implementationFactory) where TService : class where TImplementation : class, TService { if (implementationFactory == null) { throw new ArgumentNullException(nameof(implementationFactory)); } return Describe(typeof(TService), implementationFactory, ServiceLifetime.Scoped); } /// <summary> /// Creates an instance of <see cref="ServiceDescriptor"/> with the specified /// <typeparamref name="TService"/>, <paramref name="implementationFactory"/>, /// and the <see cref="ServiceLifetime.Scoped"/> lifetime. /// </summary> /// <typeparam name="TService">The type of the service.</typeparam> /// <param name="implementationFactory">A factory to create new instances of the service implementation.</param> /// <returns>A new instance of <see cref="ServiceDescriptor"/>.</returns> public static ServiceDescriptor Scoped<TService>(Func<IServiceProvider, TService> implementationFactory) where TService : class { if (implementationFactory == null) { throw new ArgumentNullException(nameof(implementationFactory)); } return Describe(typeof(TService), implementationFactory, ServiceLifetime.Scoped); } /// <summary> /// Creates an instance of <see cref="ServiceDescriptor"/> with the specified /// <paramref name="service"/>, <paramref name="implementationFactory"/>, /// and the <see cref="ServiceLifetime.Scoped"/> lifetime. /// </summary> /// <param name="service">The type of the service.</param> /// <param name="implementationFactory">A factory to create new instances of the service implementation.</param> /// <returns>A new instance of <see cref="ServiceDescriptor"/>.</returns> public static ServiceDescriptor Scoped(Type service, Func<IServiceProvider, object> implementationFactory) { if (service == null) { throw new ArgumentNullException(nameof(service)); } if (implementationFactory == null) { throw new ArgumentNullException(nameof(implementationFactory)); } return Describe(service, implementationFactory, ServiceLifetime.Scoped); } /// <summary> /// Creates an instance of <see cref="ServiceDescriptor"/> with the specified /// <typeparamref name="TService"/>, <typeparamref name="TImplementation"/>, /// and the <see cref="ServiceLifetime.Singleton"/> lifetime. /// </summary> /// <typeparam name="TService">The type of the service.</typeparam> /// <typeparam name="TImplementation">The type of the implementation.</typeparam> /// <returns>A new instance of <see cref="ServiceDescriptor"/>.</returns> public static ServiceDescriptor Singleton<TService, TImplementation>() where TService : class where TImplementation : class, TService { return Describe<TService, TImplementation>(ServiceLifetime.Singleton); } /// <summary> /// Creates an instance of <see cref="ServiceDescriptor"/> with the specified /// <paramref name="service"/> and <paramref name="implementationType"/> /// and the <see cref="ServiceLifetime.Singleton"/> lifetime. /// </summary> /// <param name="service">The type of the service.</param> /// <param name="implementationType">The type of the implementation.</param> /// <returns>A new instance of <see cref="ServiceDescriptor"/>.</returns> public static ServiceDescriptor Singleton(Type service, Type implementationType) { if (service == null) { throw new ArgumentNullException(nameof(service)); } if (implementationType == null) { throw new ArgumentNullException(nameof(implementationType)); } return Describe(service, implementationType, ServiceLifetime.Singleton); } /// <summary> /// Creates an instance of <see cref="ServiceDescriptor"/> with the specified /// <typeparamref name="TService"/>, <typeparamref name="TImplementation"/>, /// <paramref name="implementationFactory"/>, /// and the <see cref="ServiceLifetime.Singleton"/> lifetime. /// </summary> /// <typeparam name="TService">The type of the service.</typeparam> /// <typeparam name="TImplementation">The type of the implementation.</typeparam> /// <param name="implementationFactory">A factory to create new instances of the service implementation.</param> /// <returns>A new instance of <see cref="ServiceDescriptor"/>.</returns> public static ServiceDescriptor Singleton<TService, TImplementation>( Func<IServiceProvider, TImplementation> implementationFactory) where TService : class where TImplementation : class, TService { if (implementationFactory == null) { throw new ArgumentNullException(nameof(implementationFactory)); } return Describe(typeof(TService), implementationFactory, ServiceLifetime.Singleton); } /// <summary> /// Creates an instance of <see cref="ServiceDescriptor"/> with the specified /// <typeparamref name="TService"/>, <paramref name="implementationFactory"/>, /// and the <see cref="ServiceLifetime.Singleton"/> lifetime. /// </summary> /// <typeparam name="TService">The type of the service.</typeparam> /// <param name="implementationFactory">A factory to create new instances of the service implementation.</param> /// <returns>A new instance of <see cref="ServiceDescriptor"/>.</returns> public static ServiceDescriptor Singleton<TService>(Func<IServiceProvider, TService> implementationFactory) where TService : class { if (implementationFactory == null) { throw new ArgumentNullException(nameof(implementationFactory)); } return Describe(typeof(TService), implementationFactory, ServiceLifetime.Singleton); } /// <summary> /// Creates an instance of <see cref="ServiceDescriptor"/> with the specified /// <paramref name="serviceType"/>, <paramref name="implementationFactory"/>, /// and the <see cref="ServiceLifetime.Singleton"/> lifetime. /// </summary> /// <param name="serviceType">The type of the service.</param> /// <param name="implementationFactory">A factory to create new instances of the service implementation.</param> /// <returns>A new instance of <see cref="ServiceDescriptor"/>.</returns> public static ServiceDescriptor Singleton(Type serviceType, Func<IServiceProvider, object> implementationFactory) { if (serviceType == null) { throw new ArgumentNullException(nameof(serviceType)); } if (implementationFactory == null) { throw new ArgumentNullException(nameof(implementationFactory)); } return Describe(serviceType, implementationFactory, ServiceLifetime.Singleton); } /// <summary> /// Creates an instance of <see cref="ServiceDescriptor"/> with the specified /// <typeparamref name="TService"/>, <paramref name="implementationInstance"/>, /// and the <see cref="ServiceLifetime.Scoped"/> lifetime. /// </summary> /// <typeparam name="TService">The type of the service.</typeparam> /// <param name="implementationInstance">The instance of the implementation.</param> /// <returns>A new instance of <see cref="ServiceDescriptor"/>.</returns> public static ServiceDescriptor Singleton<TService>(TService implementationInstance) where TService : class { if (implementationInstance == null) { throw new ArgumentNullException(nameof(implementationInstance)); } return Singleton(typeof(TService), implementationInstance); } /// <summary> /// Creates an instance of <see cref="ServiceDescriptor"/> with the specified /// <paramref name="serviceType"/>, <paramref name="implementationInstance"/>, /// and the <see cref="ServiceLifetime.Scoped"/> lifetime. /// </summary> /// <param name="serviceType">The type of the service.</param> /// <param name="implementationInstance">The instance of the implementation.</param> /// <returns>A new instance of <see cref="ServiceDescriptor"/>.</returns> public static ServiceDescriptor Singleton(Type serviceType, object implementationInstance) { if (serviceType == null) { throw new ArgumentNullException(nameof(serviceType)); } if (implementationInstance == null) { throw new ArgumentNullException(nameof(implementationInstance)); } return new ServiceDescriptor(serviceType, implementationInstance); } private static ServiceDescriptor Describe<TService, TImplementation>(ServiceLifetime lifetime) where TService : class where TImplementation : class, TService { return Describe( typeof(TService), typeof(TImplementation), lifetime: lifetime); } /// <summary> /// Creates an instance of <see cref="ServiceDescriptor"/> with the specified /// <paramref name="serviceType"/>, <paramref name="implementationType"/>, /// and <paramref name="lifetime"/>. /// </summary> /// <param name="serviceType">The type of the service.</param> /// <param name="implementationType">The type of the implementation.</param> /// <param name="lifetime">The lifetime of the service.</param> /// <returns>A new instance of <see cref="ServiceDescriptor"/>.</returns> public static ServiceDescriptor Describe(Type serviceType, Type implementationType, ServiceLifetime lifetime) { return new ServiceDescriptor(serviceType, implementationType, lifetime); } /// <summary> /// Creates an instance of <see cref="ServiceDescriptor"/> with the specified /// <paramref name="serviceType"/>, <paramref name="implementationFactory"/>, /// and <paramref name="lifetime"/>. /// </summary> /// <param name="serviceType">The type of the service.</param> /// <param name="implementationFactory">A factory to create new instances of the service implementation.</param> /// <param name="lifetime">The lifetime of the service.</param> /// <returns>A new instance of <see cref="ServiceDescriptor"/>.</returns> public static ServiceDescriptor Describe(Type serviceType, Func<IServiceProvider, object> implementationFactory, ServiceLifetime lifetime) { return new ServiceDescriptor(serviceType, implementationFactory, lifetime); } }
里面的静态方法Transient、Scoped、Singleton其实是创建ServiceDescriptor实例,方法名称表示对应的服务生命周期
/// <summary> /// Specifies the lifetime of a service in an <see cref="IServiceCollection"/>. /// </summary> public enum ServiceLifetime { /// <summary> /// Specifies that a single instance of the service will be created. /// </summary> Singleton, /// <summary> /// Specifies that a new instance of the service will be created for each scope. /// </summary> /// <remarks> /// In ASP.NET Core applications a scope is created around each server request. /// </remarks> Scoped, /// <summary> /// Specifies that a new instance of the service will be created every time it is requested. /// </summary> Transient }
服务的生命周期有三个:Singleton、Scoped、Transient
IServiceCollection的默认扩展方法,这些方法使我们的服务注入变得更加简单
public static class ServiceCollectionDescriptorExtensions { /// <summary> /// Adds the specified <paramref name="descriptor"/> to the <paramref name="collection"/>. /// </summary> /// <param name="collection">The <see cref="IServiceCollection"/>.</param> /// <param name="descriptor">The <see cref="ServiceDescriptor"/> to add.</param> /// <returns>A reference to the current instance of <see cref="IServiceCollection"/>.</returns> public static IServiceCollection Add( this IServiceCollection collection, ServiceDescriptor descriptor) { if (collection == null) { throw new ArgumentNullException(nameof(collection)); } if (descriptor == null) { throw new ArgumentNullException(nameof(descriptor)); } collection.Add(descriptor); return collection; } /// <summary> /// Adds a sequence of <see cref="ServiceDescriptor"/> to the <paramref name="collection"/>. /// </summary> /// <param name="collection">The <see cref="IServiceCollection"/>.</param> /// <param name="descriptors">The <see cref="ServiceDescriptor"/>s to add.</param> /// <returns>A reference to the current instance of <see cref="IServiceCollection"/>.</returns> public static IServiceCollection Add( this IServiceCollection collection, IEnumerable<ServiceDescriptor> descriptors) { if (collection == null) { throw new ArgumentNullException(nameof(collection)); } if (descriptors == null) { throw new ArgumentNullException(nameof(descriptors)); } foreach (var descriptor in descriptors) { collection.Add(descriptor); } return collection; } /// <summary> /// Adds the specified <paramref name="descriptor"/> to the <paramref name="collection"/> if the /// service type hasn't already been registered. /// </summary> /// <param name="collection">The <see cref="IServiceCollection"/>.</param> /// <param name="descriptor">The <see cref="ServiceDescriptor"/> to add.</param> public static void TryAdd( this IServiceCollection collection, ServiceDescriptor descriptor) { if (collection == null) { throw new ArgumentNullException(nameof(collection)); } if (descriptor == null) { throw new ArgumentNullException(nameof(descriptor)); } if (!collection.Any(d => d.ServiceType == descriptor.ServiceType)) { collection.Add(descriptor); } } /// <summary> /// Adds the specified <paramref name="descriptors"/> to the <paramref name="collection"/> if the /// service type hasn't already been registered. /// </summary> /// <param name="collection">The <see cref="IServiceCollection"/>.</param> /// <param name="descriptors">The <see cref="ServiceDescriptor"/>s to add.</param> public static void TryAdd( this IServiceCollection collection, IEnumerable<ServiceDescriptor> descriptors) { if (collection == null) { throw new ArgumentNullException(nameof(collection)); } if (descriptors == null) { throw new ArgumentNullException(nameof(descriptors)); } foreach (var d in descriptors) { collection.TryAdd(d); } } /// <summary> /// Adds the specified <paramref name="service"/> as a <see cref="ServiceLifetime.Transient"/> service /// to the <paramref name="collection"/> if the service type hasn't already been registered. /// </summary> /// <param name="collection">The <see cref="IServiceCollection"/>.</param> /// <param name="service">The type of the service to register.</param> public static void TryAddTransient( this IServiceCollection collection, Type service) { if (collection == null) { throw new ArgumentNullException(nameof(collection)); } if (service == null) { throw new ArgumentNullException(nameof(service)); } var descriptor = ServiceDescriptor.Transient(service, service); TryAdd(collection, descriptor); } /// <summary> /// Adds the specified <paramref name="service"/> as a <see cref="ServiceLifetime.Transient"/> service /// with the <paramref name="implementationType"/> implementation /// to the <paramref name="collection"/> if the service type hasn't already been registered. /// </summary> /// <param name="collection">The <see cref="IServiceCollection"/>.</param> /// <param name="service">The type of the service to register.</param> /// <param name="implementationType">The implementation type of the service.</param> public static void TryAddTransient( this IServiceCollection collection, Type service, Type implementationType) { if (collection == null) { throw new ArgumentNullException(nameof(collection)); } if (service == null) { throw new ArgumentNullException(nameof(service)); } if (implementationType == null) { throw new ArgumentNullException(nameof(implementationType)); } var descriptor = ServiceDescriptor.Transient(service, implementationType); TryAdd(collection, descriptor); } /// <summary> /// Adds the specified <paramref name="service"/> as a <see cref="ServiceLifetime.Transient"/> service /// using the factory specified in <paramref name="implementationFactory"/> /// to the <paramref name="collection"/> if the service type hasn't already been registered. /// </summary> /// <param name="collection">The <see cref="IServiceCollection"/>.</param> /// <param name="service">The type of the service to register.</param> /// <param name="implementationFactory">The factory that creates the service.</param> public static void TryAddTransient( this IServiceCollection collection, Type service, Func<IServiceProvider, object> implementationFactory) { if (collection == null) { throw new ArgumentNullException(nameof(collection)); } if (service == null) { throw new ArgumentNullException(nameof(service)); } if (implementationFactory == null) { throw new ArgumentNullException(nameof(implementationFactory)); } var descriptor = ServiceDescriptor.Transient(service, implementationFactory); TryAdd(collection, descriptor); } /// <summary> /// Adds the specified <typeparamref name="TService"/> as a <see cref="ServiceLifetime.Transient"/> service /// to the <paramref name="collection"/> if the service type hasn't already been registered. /// </summary> /// <typeparam name="TService">The type of the service to add.</typeparam> /// <param name="collection">The <see cref="IServiceCollection"/>.</param> public static void TryAddTransient<TService>(this IServiceCollection collection) where TService : class { if (collection == null) { throw new ArgumentNullException(nameof(collection)); } TryAddTransient(collection, typeof(TService), typeof(TService)); } /// <summary> /// Adds the specified <typeparamref name="TService"/> as a <see cref="ServiceLifetime.Transient"/> service /// implementation type specified in <typeparamref name="TImplementation"/> /// to the <paramref name="collection"/> if the service type hasn't already been registered. /// </summary> /// <typeparam name="TService">The type of the service to add.</typeparam> /// <typeparam name="TImplementation">The type of the implementation to use.</typeparam> /// <param name="collection">The <see cref="IServiceCollection"/>.</param> public static void TryAddTransient<TService, TImplementation>(this IServiceCollection collection) where TService : class where TImplementation : class, TService { if (collection == null) { throw new ArgumentNullException(nameof(collection)); } TryAddTransient(collection, typeof(TService), typeof(TImplementation)); } /// <summary> /// Adds the specified <typeparamref name="TService"/> as a <see cref="ServiceLifetime.Transient"/> service /// using the factory specified in <paramref name="implementationFactory"/> /// to the <paramref name="services"/> if the service type hasn't already been registered. /// </summary> /// <typeparam name="TService">The type of the service to add.</typeparam> /// <param name="services">The <see cref="IServiceCollection"/>.</param> /// <param name="implementationFactory">The factory that creates the service.</param> public static void TryAddTransient<TService>( this IServiceCollection services, Func<IServiceProvider, TService> implementationFactory) where TService : class { services.TryAdd(ServiceDescriptor.Transient(implementationFactory)); } /// <summary> /// Adds the specified <paramref name="service"/> as a <see cref="ServiceLifetime.Scoped"/> service /// to the <paramref name="collection"/> if the service type hasn't already been registered. /// </summary> /// <param name="collection">The <see cref="IServiceCollection"/>.</param> /// <param name="service">The type of the service to register.</param> public static void TryAddScoped( this IServiceCollection collection, Type service) { if (collection == null) { throw new ArgumentNullException(nameof(collection)); } if (service == null) { throw new ArgumentNullException(nameof(service)); } var descriptor = ServiceDescriptor.Scoped(service, service); TryAdd(collection, descriptor); } /// <summary> /// Adds the specified <paramref name="service"/> as a <see cref="ServiceLifetime.Scoped"/> service /// with the <paramref name="implementationType"/> implementation /// to the <paramref name="collection"/> if the service type hasn't already been registered. /// </summary> /// <param name="collection">The <see cref="IServiceCollection"/>.</param> /// <param name="service">The type of the service to register.</param> /// <param name="implementationType">The implementation type of the service.</param> public static void TryAddScoped( this IServiceCollection collection, Type service, Type implementationType) { if (collection == null) { throw new ArgumentNullException(nameof(collection)); } if (service == null) { throw new ArgumentNullException(nameof(service)); } if (implementationType == null) { throw new ArgumentNullException(nameof(implementationType)); } var descriptor = ServiceDescriptor.Scoped(service, implementationType); TryAdd(collection, descriptor); } /// <summary> /// Adds the specified <paramref name="service"/> as a <see cref="ServiceLifetime.Scoped"/> service /// using the factory specified in <paramref name="implementationFactory"/> /// to the <paramref name="collection"/> if the service type hasn't already been registered. /// </summary> /// <param name="collection">The <see cref="IServiceCollection"/>.</param> /// <param name="service">The type of the service to register.</param> /// <param name="implementationFactory">The factory that creates the service.</param> public static void TryAddScoped( this IServiceCollection collection, Type service, Func<IServiceProvider, object> implementationFactory) { if (collection == null) { throw new ArgumentNullException(nameof(collection)); } if (service == null) { throw new ArgumentNullException(nameof(service)); } if (implementationFactory == null) { throw new ArgumentNullException(nameof(implementationFactory)); } var descriptor = ServiceDescriptor.Scoped(service, implementationFactory); TryAdd(collection, descriptor); } /// <summary> /// Adds the specified <typeparamref name="TService"/> as a <see cref="ServiceLifetime.Scoped"/> service /// to the <paramref name="collection"/> if the service type hasn't already been registered. /// </summary> /// <typeparam name="TService">The type of the service to add.</typeparam> /// <param name="collection">The <see cref="IServiceCollection"/>.</param> public static void TryAddScoped<TService>(this IServiceCollection collection) where TService : class { if (collection == null) { throw new ArgumentNullException(nameof(collection)); } TryAddScoped(collection, typeof(TService), typeof(TService)); } /// <summary> /// Adds the specified <typeparamref name="TService"/> as a <see cref="ServiceLifetime.Scoped"/> service /// implementation type specified in <typeparamref name="TImplementation"/> /// to the <paramref name="collection"/> if the service type hasn't already been registered. /// </summary> /// <typeparam name="TService">The type of the service to add.</typeparam> /// <typeparam name="TImplementation">The type of the implementation to use.</typeparam> /// <param name="collection">The <see cref="IServiceCollection"/>.</param> public static void TryAddScoped<TService, TImplementation>(this IServiceCollection collection) where TService : class where TImplementation : class, TService { if (collection == null) { throw new ArgumentNullException(nameof(collection)); } TryAddScoped(collection, typeof(TService), typeof(TImplementation)); } /// <summary> /// Adds the specified <typeparamref name="TService"/> as a <see cref="ServiceLifetime.Scoped"/> service /// using the factory specified in <paramref name="implementationFactory"/> /// to the <paramref name="services"/> if the service type hasn't already been registered. /// </summary> /// <typeparam name="TService">The type of the service to add.</typeparam> /// <param name="services">The <see cref="IServiceCollection"/>.</param> /// <param name="implementationFactory">The factory that creates the service.</param> public static void TryAddScoped<TService>( this IServiceCollection services, Func<IServiceProvider, TService> implementationFactory) where TService : class { services.TryAdd(ServiceDescriptor.Scoped(implementationFactory)); } /// <summary> /// Adds the specified <paramref name="service"/> as a <see cref="ServiceLifetime.Singleton"/> service /// to the <paramref name="collection"/> if the service type hasn't already been registered. /// </summary> /// <param name="collection">The <see cref="IServiceCollection"/>.</param> /// <param name="service">The type of the service to register.</param> public static void TryAddSingleton( this IServiceCollection collection, Type service) { if (collection == null) { throw new ArgumentNullException(nameof(collection)); } if (service == null) { throw new ArgumentNullException(nameof(service)); } var descriptor = ServiceDescriptor.Singleton(service, service); TryAdd(collection, descriptor); } /// <summary> /// Adds the specified <paramref name="service"/> as a <see cref="ServiceLifetime.Singleton"/> service /// with the <paramref name="implementationType"/> implementation /// to the <paramref name="collection"/> if the service type hasn't already been registered. /// </summary> /// <param name="collection">The <see cref="IServiceCollection"/>.</param> /// <param name="service">The type of the service to register.</param> /// <param name="implementationType">The implementation type of the service.</param> public static void TryAddSingleton( this IServiceCollection collection, Type service, Type implementationType) { if (collection == null) { throw new ArgumentNullException(nameof(collection)); } if (service == null) { throw new ArgumentNullException(nameof(service)); } if (implementationType == null) { throw new ArgumentNullException(nameof(implementationType)); } var descriptor = ServiceDescriptor.Singleton(service, implementationType); TryAdd(collection, descriptor); } /// <summary> /// Adds the specified <paramref name="service"/> as a <see cref="ServiceLifetime.Singleton"/> service /// using the factory specified in <paramref name="implementationFactory"/> /// to the <paramref name="collection"/> if the service type hasn't already been registered. /// </summary> /// <param name="collection">The <see cref="IServiceCollection"/>.</param> /// <param name="service">The type of the service to register.</param> /// <param name="implementationFactory">The factory that creates the service.</param> public static void TryAddSingleton( this IServiceCollection collection, Type service, Func<IServiceProvider, object> implementationFactory) { if (collection == null) { throw new ArgumentNullException(nameof(collection)); } if (service == null) { throw new ArgumentNullException(nameof(service)); } if (implementationFactory == null) { throw new ArgumentNullException(nameof(implementationFactory)); } var descriptor = ServiceDescriptor.Singleton(service, implementationFactory); TryAdd(collection, descriptor); } /// <summary> /// Adds the specified <typeparamref name="TService"/> as a <see cref="ServiceLifetime.Singleton"/> service /// to the <paramref name="collection"/> if the service type hasn't already been registered. /// </summary> /// <typeparam name="TService">The type of the service to add.</typeparam> /// <param name="collection">The <see cref="IServiceCollection"/>.</param> public static void TryAddSingleton<TService>(this IServiceCollection collection) where TService : class { if (collection == null) { throw new ArgumentNullException(nameof(collection)); } TryAddSingleton(collection, typeof(TService), typeof(TService)); } /// <summary> /// Adds the specified <typeparamref name="TService"/> as a <see cref="ServiceLifetime.Singleton"/> service /// implementation type specified in <typeparamref name="TImplementation"/> /// to the <paramref name="collection"/> if the service type hasn't already been registered. /// </summary> /// <typeparam name="TService">The type of the service to add.</typeparam> /// <typeparam name="TImplementation">The type of the implementation to use.</typeparam> /// <param name="collection">The <see cref="IServiceCollection"/>.</param> public static void TryAddSingleton<TService, TImplementation>(this IServiceCollection collection) where TService : class where TImplementation : class, TService { if (collection == null) { throw new ArgumentNullException(nameof(collection)); } TryAddSingleton(collection, typeof(TService), typeof(TImplementation)); } /// <summary> /// Adds the specified <typeparamref name="TService"/> as a <see cref="ServiceLifetime.Singleton"/> service /// with an instance specified in <paramref name="instance"/> /// to the <paramref name="collection"/> if the service type hasn't already been registered. /// </summary> /// <typeparam name="TService">The type of the service to add.</typeparam> /// <param name="collection">The <see cref="IServiceCollection"/>.</param> /// <param name="instance">The instance of the service to add.</param> public static void TryAddSingleton<TService>(this IServiceCollection collection, TService instance) where TService : class { if (collection == null) { throw new ArgumentNullException(nameof(collection)); } if (instance == null) { throw new ArgumentNullException(nameof(instance)); } var descriptor = ServiceDescriptor.Singleton(typeof(TService), instance); TryAdd(collection, descriptor); } /// <summary> /// Adds the specified <typeparamref name="TService"/> as a <see cref="ServiceLifetime.Singleton"/> service /// using the factory specified in <paramref name="implementationFactory"/> /// to the <paramref name="services"/> if the service type hasn't already been registered. /// </summary> /// <typeparam name="TService">The type of the service to add.</typeparam> /// <param name="services">The <see cref="IServiceCollection"/>.</param> /// <param name="implementationFactory">The factory that creates the service.</param> public static void TryAddSingleton<TService>( this IServiceCollection services, Func<IServiceProvider, TService> implementationFactory) where TService : class { services.TryAdd(ServiceDescriptor.Singleton(implementationFactory)); } /// <summary> /// Adds a <see cref="ServiceDescriptor"/> if an existing descriptor with the same /// <see cref="ServiceDescriptor.ServiceType"/> and an implementation that does not already exist /// in <paramref name="services."/>. /// </summary> /// <param name="services">The <see cref="IServiceCollection"/>.</param> /// <param name="descriptor">The <see cref="ServiceDescriptor"/>.</param> /// <remarks> /// Use <see cref="TryAddEnumerable(IServiceCollection, ServiceDescriptor)"/> when registering a service implementation of a /// service type that /// supports multiple registrations of the same service type. Using /// <see cref="Add(IServiceCollection, ServiceDescriptor)"/> is not idempotent and can add /// duplicate /// <see cref="ServiceDescriptor"/> instances if called twice. Using /// <see cref="TryAddEnumerable(IServiceCollection, ServiceDescriptor)"/> will prevent registration /// of multiple implementation types. /// </remarks> public static void TryAddEnumerable( this IServiceCollection services, ServiceDescriptor descriptor) { if (services == null) { throw new ArgumentNullException(nameof(services)); } if (descriptor == null) { throw new ArgumentNullException(nameof(descriptor)); } var implementationType = descriptor.GetImplementationType(); if (implementationType == typeof(object) || implementationType == descriptor.ServiceType) { throw new ArgumentException( Resources.FormatTryAddIndistinguishableTypeToEnumerable( implementationType, descriptor.ServiceType), nameof(descriptor)); } if (!services.Any(d => d.ServiceType == descriptor.ServiceType && d.GetImplementationType() == implementationType)) { services.Add(descriptor); } } /// <summary> /// Adds the specified <see cref="ServiceDescriptor"/>s if an existing descriptor with the same /// <see cref="ServiceDescriptor.ServiceType"/> and an implementation that does not already exist /// in <paramref name="services."/>. /// </summary> /// <param name="services">The <see cref="IServiceCollection"/>.</param> /// <param name="descriptors">The <see cref="ServiceDescriptor"/>s.</param> /// <remarks> /// Use <see cref="TryAddEnumerable(IServiceCollection, ServiceDescriptor)"/> when registering a service /// implementation of a service type that /// supports multiple registrations of the same service type. Using /// <see cref="Add(IServiceCollection, ServiceDescriptor)"/> is not idempotent and can add /// duplicate /// <see cref="ServiceDescriptor"/> instances if called twice. Using /// <see cref="TryAddEnumerable(IServiceCollection, ServiceDescriptor)"/> will prevent registration /// of multiple implementation types. /// </remarks> public static void TryAddEnumerable( this IServiceCollection services, IEnumerable<ServiceDescriptor> descriptors) { if (services == null) { throw new ArgumentNullException(nameof(services)); } if (descriptors == null) { throw new ArgumentNullException(nameof(descriptors)); } foreach (var d in descriptors) { services.TryAddEnumerable(d); } } /// <summary> /// Removes the first service in <see cref="IServiceCollection"/> with the same service type /// as <paramref name="descriptor"/> and adds <paramref name="descriptor"/> to the collection. /// </summary> /// <param name="collection">The <see cref="IServiceCollection"/>.</param> /// <param name="descriptor">The <see cref="ServiceDescriptor"/> to replace with.</param> /// <returns>The <see cref="IServiceCollection"/> for chaining.</returns> public static IServiceCollection Replace( this IServiceCollection collection, ServiceDescriptor descriptor) { if (collection == null) { throw new ArgumentNullException(nameof(collection)); } if (descriptor == null) { throw new ArgumentNullException(nameof(descriptor)); } var registeredServiceDescriptor = collection.FirstOrDefault(s => s.ServiceType == descriptor.ServiceType); if (registeredServiceDescriptor != null) { collection.Remove(registeredServiceDescriptor); } collection.Add(descriptor); return collection; } /// <summary> /// Removes all services of type <typeparamref name="T"/> in <see cref="IServiceCollection"/>. /// </summary> /// <param name="collection">The <see cref="IServiceCollection"/>.</param> /// <returns>The <see cref="IServiceCollection"/> for chaining.</returns> public static IServiceCollection RemoveAll<T>(this IServiceCollection collection) { return RemoveAll(collection, typeof(T)); } /// <summary> /// Removes all services of type <paramref name="serviceType"/> in <see cref="IServiceCollection"/>. /// </summary> /// <param name="collection">The <see cref="IServiceCollection"/>.</param> /// <param name="serviceType">The service type to remove.</param> /// <returns>The <see cref="IServiceCollection"/> for chaining.</returns> public static IServiceCollection RemoveAll(this IServiceCollection collection, Type serviceType) { if (serviceType == null) { throw new ArgumentNullException(nameof(serviceType)); } for (var i = collection.Count - 1; i >= 0; i--) { var descriptor = collection[i]; if (descriptor.ServiceType == serviceType) { collection.RemoveAt(i); } } return collection; } }
注意一下几个方法:TryAddEnumerable、Replace
/// <summary> /// Extension methods for adding services to an <see cref="IServiceCollection" />. /// </summary> public static class ServiceCollectionServiceExtensions { /// <summary> /// Adds a transient service of the type specified in <paramref name="serviceType"/> with an /// implementation of the type specified in <paramref name="implementationType"/> to the /// specified <see cref="IServiceCollection"/>. /// </summary> /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param> /// <param name="serviceType">The type of the service to register.</param> /// <param name="implementationType">The implementation type of the service.</param> /// <returns>A reference to this instance after the operation has completed.</returns> /// <seealso cref="ServiceLifetime.Transient"/> public static IServiceCollection AddTransient( this IServiceCollection services, Type serviceType, Type implementationType) { if (services == null) { throw new ArgumentNullException(nameof(services)); } if (serviceType == null) { throw new ArgumentNullException(nameof(serviceType)); } if (implementationType == null) { throw new ArgumentNullException(nameof(implementationType)); } return Add(services, serviceType, implementationType, ServiceLifetime.Transient); } /// <summary> /// Adds a transient service of the type specified in <paramref name="serviceType"/> with a /// factory specified in <paramref name="implementationFactory"/> to the /// specified <see cref="IServiceCollection"/>. /// </summary> /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param> /// <param name="serviceType">The type of the service to register.</param> /// <param name="implementationFactory">The factory that creates the service.</param> /// <returns>A reference to this instance after the operation has completed.</returns> /// <seealso cref="ServiceLifetime.Transient"/> public static IServiceCollection AddTransient( this IServiceCollection services, Type serviceType, Func<IServiceProvider, object> implementationFactory) { if (services == null) { throw new ArgumentNullException(nameof(services)); } if (serviceType == null) { throw new ArgumentNullException(nameof(serviceType)); } if (implementationFactory == null) { throw new ArgumentNullException(nameof(implementationFactory)); } return Add(services, serviceType, implementationFactory, ServiceLifetime.Transient); } /// <summary> /// Adds a transient service of the type specified in <typeparamref name="TService"/> with an /// implementation type specified in <typeparamref name="TImplementation"/> to the /// specified <see cref="IServiceCollection"/>. /// </summary> /// <typeparam name="TService">The type of the service to add.</typeparam> /// <typeparam name="TImplementation">The type of the implementation to use.</typeparam> /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param> /// <returns>A reference to this instance after the operation has completed.</returns> /// <seealso cref="ServiceLifetime.Transient"/> public static IServiceCollection AddTransient<TService, TImplementation>(this IServiceCollection services) where TService : class where TImplementation : class, TService { if (services == null) { throw new ArgumentNullException(nameof(services)); } return services.AddTransient(typeof(TService), typeof(TImplementation)); } /// <summary> /// Adds a transient service of the type specified in <paramref name="serviceType"/> to the /// specified <see cref="IServiceCollection"/>. /// </summary> /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param> /// <param name="serviceType">The type of the service to register and the implementation to use.</param> /// <returns>A reference to this instance after the operation has completed.</returns> /// <seealso cref="ServiceLifetime.Transient"/> public static IServiceCollection AddTransient( this IServiceCollection services, Type serviceType) { if (services == null) { throw new ArgumentNullException(nameof(services)); } if (serviceType == null) { throw new ArgumentNullException(nameof(serviceType)); } return services.AddTransient(serviceType, serviceType); } /// <summary> /// Adds a transient service of the type specified in <typeparamref name="TService"/> to the /// specified <see cref="IServiceCollection"/>. /// </summary> /// <typeparam name="TService">The type of the service to add.</typeparam> /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param> /// <returns>A reference to this instance after the operation has completed.</returns> /// <seealso cref="ServiceLifetime.Transient"/> public static IServiceCollection AddTransient<TService>(this IServiceCollection services) where TService : class { if (services == null) { throw new ArgumentNullException(nameof(services)); } return services.AddTransient(typeof(TService)); } /// <summary> /// Adds a transient service of the type specified in <typeparamref name="TService"/> with a /// factory specified in <paramref name="implementationFactory"/> to the /// specified <see cref="IServiceCollection"/>. /// </summary> /// <typeparam name="TService">The type of the service to add.</typeparam> /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param> /// <param name="implementationFactory">The factory that creates the service.</param> /// <returns>A reference to this instance after the operation has completed.</returns> /// <seealso cref="ServiceLifetime.Transient"/> public static IServiceCollection AddTransient<TService>( this IServiceCollection services, Func<IServiceProvider, TService> implementationFactory) where TService : class { if (services == null) { throw new ArgumentNullException(nameof(services)); } if (implementationFactory == null) { throw new ArgumentNullException(nameof(implementationFactory)); } return services.AddTransient(typeof(TService), implementationFactory); } /// <summary> /// Adds a transient service of the type specified in <typeparamref name="TService"/> with an /// implementation type specified in <typeparamref name="TImplementation" /> using the /// factory specified in <paramref name="implementationFactory"/> to the /// specified <see cref="IServiceCollection"/>. /// </summary> /// <typeparam name="TService">The type of the service to add.</typeparam> /// <typeparam name="TImplementation">The type of the implementation to use.</typeparam> /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param> /// <param name="implementationFactory">The factory that creates the service.</param> /// <returns>A reference to this instance after the operation has completed.</returns> /// <seealso cref="ServiceLifetime.Transient"/> public static IServiceCollection AddTransient<TService, TImplementation>( this IServiceCollection services, Func<IServiceProvider, TImplementation> implementationFactory) where TService : class where TImplementation : class, TService { if (services == null) { throw new ArgumentNullException(nameof(services)); } if (implementationFactory == null) { throw new ArgumentNullException(nameof(implementationFactory)); } return services.AddTransient(typeof(TService), implementationFactory); } /// <summary> /// Adds a scoped service of the type specified in <paramref name="serviceType"/> with an /// implementation of the type specified in <paramref name="implementationType"/> to the /// specified <see cref="IServiceCollection"/>. /// </summary> /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param> /// <param name="serviceType">The type of the service to register.</param> /// <param name="implementationType">The implementation type of the service.</param> /// <returns>A reference to this instance after the operation has completed.</returns> /// <seealso cref="ServiceLifetime.Scoped"/> public static IServiceCollection AddScoped( this IServiceCollection services, Type serviceType, Type implementationType) { if (services == null) { throw new ArgumentNullException(nameof(services)); } if (serviceType == null) { throw new ArgumentNullException(nameof(serviceType)); } if (implementationType == null) { throw new ArgumentNullException(nameof(implementationType)); } return Add(services, serviceType, implementationType, ServiceLifetime.Scoped); } /// <summary> /// Adds a scoped service of the type specified in <paramref name="serviceType"/> with a /// factory specified in <paramref name="implementationFactory"/> to the /// specified <see cref="IServiceCollection"/>. /// </summary> /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param> /// <param name="serviceType">The type of the service to register.</param> /// <param name="implementationFactory">The factory that creates the service.</param> /// <returns>A reference to this instance after the operation has completed.</returns> /// <seealso cref="ServiceLifetime.Scoped"/> public static IServiceCollection AddScoped( this IServiceCollection services, Type serviceType, Func<IServiceProvider, object> implementationFactory) { if (services == null) { throw new ArgumentNullException(nameof(services)); } if (serviceType == null) { throw new ArgumentNullException(nameof(serviceType)); } if (implementationFactory == null) { throw new ArgumentNullException(nameof(implementationFactory)); } return Add(services, serviceType, implementationFactory, ServiceLifetime.Scoped); } /// <summary> /// Adds a scoped service of the type specified in <typeparamref name="TService"/> with an /// implementation type specified in <typeparamref name="TImplementation"/> to the /// specified <see cref="IServiceCollection"/>. /// </summary> /// <typeparam name="TService">The type of the service to add.</typeparam> /// <typeparam name="TImplementation">The type of the implementation to use.</typeparam> /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param> /// <returns>A reference to this instance after the operation has completed.</returns> /// <seealso cref="ServiceLifetime.Scoped"/> public static IServiceCollection AddScoped<TService, TImplementation>(this IServiceCollection services) where TService : class where TImplementation : class, TService { if (services == null) { throw new ArgumentNullException(nameof(services)); } return services.AddScoped(typeof(TService), typeof(TImplementation)); } /// <summary> /// Adds a scoped service of the type specified in <paramref name="serviceType"/> to the /// specified <see cref="IServiceCollection"/>. /// </summary> /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param> /// <param name="serviceType">The type of the service to register and the implementation to use.</param> /// <returns>A reference to this instance after the operation has completed.</returns> /// <seealso cref="ServiceLifetime.Scoped"/> public static IServiceCollection AddScoped( this IServiceCollection services, Type serviceType) { if (services == null) { throw new ArgumentNullException(nameof(services)); } if (serviceType == null) { throw new ArgumentNullException(nameof(serviceType)); } return services.AddScoped(serviceType, serviceType); } /// <summary> /// Adds a scoped service of the type specified in <typeparamref name="TService"/> to the /// specified <see cref="IServiceCollection"/>. /// </summary> /// <typeparam name="TService">The type of the service to add.</typeparam> /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param> /// <returns>A reference to this instance after the operation has completed.</returns> /// <seealso cref="ServiceLifetime.Scoped"/> public static IServiceCollection AddScoped<TService>(this IServiceCollection services) where TService : class { if (services == null) { throw new ArgumentNullException(nameof(services)); } return services.AddScoped(typeof(TService)); } /// <summary> /// Adds a scoped service of the type specified in <typeparamref name="TService"/> with a /// factory specified in <paramref name="implementationFactory"/> to the /// specified <see cref="IServiceCollection"/>. /// </summary> /// <typeparam name="TService">The type of the service to add.</typeparam> /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param> /// <param name="implementationFactory">The factory that creates the service.</param> /// <returns>A reference to this instance after the operation has completed.</returns> /// <seealso cref="ServiceLifetime.Scoped"/> public static IServiceCollection AddScoped<TService>( this IServiceCollection services, Func<IServiceProvider, TService> implementationFactory) where TService : class { if (services == null) { throw new ArgumentNullException(nameof(services)); } if (implementationFactory == null) { throw new ArgumentNullException(nameof(implementationFactory)); } return services.AddScoped(typeof(TService), implementationFactory); } /// <summary> /// Adds a scoped service of the type specified in <typeparamref name="TService"/> with an /// implementation type specified in <typeparamref name="TImplementation" /> using the /// factory specified in <paramref name="implementationFactory"/> to the /// specified <see cref="IServiceCollection"/>. /// </summary> /// <typeparam name="TService">The type of the service to add.</typeparam> /// <typeparam name="TImplementation">The type of the implementation to use.</typeparam> /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param> /// <param name="implementationFactory">The factory that creates the service.</param> /// <returns>A reference to this instance after the operation has completed.</returns> /// <seealso cref="ServiceLifetime.Scoped"/> public static IServiceCollection AddScoped<TService, TImplementation>( this IServiceCollection services, Func<IServiceProvider, TImplementation> implementationFactory) where TService : class where TImplementation : class, TService { if (services == null) { throw new ArgumentNullException(nameof(services)); } if (implementationFactory == null) { throw new ArgumentNullException(nameof(implementationFactory)); } return services.AddScoped(typeof(TService), implementationFactory); } /// <summary> /// Adds a singleton service of the type specified in <paramref name="serviceType"/> with an /// implementation of the type specified in <paramref name="implementationType"/> to the /// specified <see cref="IServiceCollection"/>. /// </summary> /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param> /// <param name="serviceType">The type of the service to register.</param> /// <param name="implementationType">The implementation type of the service.</param> /// <returns>A reference to this instance after the operation has completed.</returns> /// <seealso cref="ServiceLifetime.Singleton"/> public static IServiceCollection AddSingleton( this IServiceCollection services, Type serviceType, Type implementationType) { if (services == null) { throw new ArgumentNullException(nameof(services)); } if (serviceType == null) { throw new ArgumentNullException(nameof(serviceType)); } if (implementationType == null) { throw new ArgumentNullException(nameof(implementationType)); } return Add(services, serviceType, implementationType, ServiceLifetime.Singleton); } /// <summary> /// Adds a singleton service of the type specified in <paramref name="serviceType"/> with a /// factory specified in <paramref name="implementationFactory"/> to the /// specified <see cref="IServiceCollection"/>. /// </summary> /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param> /// <param name="serviceType">The type of the service to register.</param> /// <param name="implementationFactory">The factory that creates the service.</param> /// <returns>A reference to this instance after the operation has completed.</returns> /// <seealso cref="ServiceLifetime.Singleton"/> public static IServiceCollection AddSingleton( this IServiceCollection services, Type serviceType, Func<IServiceProvider, object> implementationFactory) { if (services == null) { throw new ArgumentNullException(nameof(services)); } if (serviceType == null) { throw new ArgumentNullException(nameof(serviceType)); } if (implementationFactory == null) { throw new ArgumentNullException(nameof(implementationFactory)); } return Add(services, serviceType, implementationFactory, ServiceLifetime.Singleton); } /// <summary> /// Adds a singleton service of the type specified in <typeparamref name="TService"/> with an /// implementation type specified in <typeparamref name="TImplementation"/> to the /// specified <see cref="IServiceCollection"/>. /// </summary> /// <typeparam name="TService">The type of the service to add.</typeparam> /// <typeparam name="TImplementation">The type of the implementation to use.</typeparam> /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param> /// <returns>A reference to this instance after the operation has completed.</returns> /// <seealso cref="ServiceLifetime.Singleton"/> public static IServiceCollection AddSingleton<TService, TImplementation>(this IServiceCollection services) where TService : class where TImplementation : class, TService { if (services == null) { throw new ArgumentNullException(nameof(services)); } return services.AddSingleton(typeof(TService), typeof(TImplementation)); } /// <summary> /// Adds a singleton service of the type specified in <paramref name="serviceType"/> to the /// specified <see cref="IServiceCollection"/>. /// </summary> /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param> /// <param name="serviceType">The type of the service to register and the implementation to use.</param> /// <returns>A reference to this instance after the operation has completed.</returns> /// <seealso cref="ServiceLifetime.Singleton"/> public static IServiceCollection AddSingleton( this IServiceCollection services, Type serviceType) { if (services == null) { throw new ArgumentNullException(nameof(services)); } if (serviceType == null) { throw new ArgumentNullException(nameof(serviceType)); } return services.AddSingleton(serviceType, serviceType); } /// <summary> /// Adds a singleton service of the type specified in <typeparamref name="TService"/> to the /// specified <see cref="IServiceCollection"/>. /// </summary> /// <typeparam name="TService">The type of the service to add.</typeparam> /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param> /// <returns>A reference to this instance after the operation has completed.</returns> /// <seealso cref="ServiceLifetime.Singleton"/> public static IServiceCollection AddSingleton<TService>(this IServiceCollection services) where TService : class { if (services == null) { throw new ArgumentNullException(nameof(services)); } return services.AddSingleton(typeof(TService)); } /// <summary> /// Adds a singleton service of the type specified in <typeparamref name="TService"/> with a /// factory specified in <paramref name="implementationFactory"/> to the /// specified <see cref="IServiceCollection"/>. /// </summary> /// <typeparam name="TService">The type of the service to add.</typeparam> /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param> /// <param name="implementationFactory">The factory that creates the service.</param> /// <returns>A reference to this instance after the operation has completed.</returns> /// <seealso cref="ServiceLifetime.Singleton"/> public static IServiceCollection AddSingleton<TService>( this IServiceCollection services, Func<IServiceProvider, TService> implementationFactory) where TService : class { if (services == null) { throw new ArgumentNullException(nameof(services)); } if (implementationFactory == null) { throw new ArgumentNullException(nameof(implementationFactory)); } return services.AddSingleton(typeof(TService), implementationFactory); } /// <summary> /// Adds a singleton service of the type specified in <typeparamref name="TService"/> with an /// implementation type specified in <typeparamref name="TImplementation" /> using the /// factory specified in <paramref name="implementationFactory"/> to the /// specified <see cref="IServiceCollection"/>. /// </summary> /// <typeparam name="TService">The type of the service to add.</typeparam> /// <typeparam name="TImplementation">The type of the implementation to use.</typeparam> /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param> /// <param name="implementationFactory">The factory that creates the service.</param> /// <returns>A reference to this instance after the operation has completed.</returns> /// <seealso cref="ServiceLifetime.Singleton"/> public static IServiceCollection AddSingleton<TService, TImplementation>( this IServiceCollection services, Func<IServiceProvider, TImplementation> implementationFactory) where TService : class where TImplementation : class, TService { if (services == null) { throw new ArgumentNullException(nameof(services)); } if (implementationFactory == null) { throw new ArgumentNullException(nameof(implementationFactory)); } return services.AddSingleton(typeof(TService), implementationFactory); } /// <summary> /// Adds a singleton service of the type specified in <paramref name="serviceType"/> with an /// instance specified in <paramref name="implementationInstance"/> to the /// specified <see cref="IServiceCollection"/>. /// </summary> /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param> /// <param name="serviceType">The type of the service to register.</param> /// <param name="implementationInstance">The instance of the service.</param> /// <returns>A reference to this instance after the operation has completed.</returns> /// <seealso cref="ServiceLifetime.Singleton"/> public static IServiceCollection AddSingleton( this IServiceCollection services, Type serviceType, object implementationInstance) { if (services == null) { throw new ArgumentNullException(nameof(services)); } if (serviceType == null) { throw new ArgumentNullException(nameof(serviceType)); } if (implementationInstance == null) { throw new ArgumentNullException(nameof(implementationInstance)); } var serviceDescriptor = new ServiceDescriptor(serviceType, implementationInstance); services.Add(serviceDescriptor); return services; } /// <summary> /// Adds a singleton service of the type specified in <typeparamref name="TService" /> with an /// instance specified in <paramref name="implementationInstance"/> to the /// specified <see cref="IServiceCollection"/>. /// </summary> /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param> /// <param name="implementationInstance">The instance of the service.</param> /// <returns>A reference to this instance after the operation has completed.</returns> /// <seealso cref="ServiceLifetime.Singleton"/> public static IServiceCollection AddSingleton<TService>( this IServiceCollection services, TService implementationInstance) where TService : class { if (services == null) { throw new ArgumentNullException(nameof(services)); } if (implementationInstance == null) { throw new ArgumentNullException(nameof(implementationInstance)); } return services.AddSingleton(typeof(TService), implementationInstance); } private static IServiceCollection Add( IServiceCollection collection, Type serviceType, Type implementationType, ServiceLifetime lifetime) { var descriptor = new ServiceDescriptor(serviceType, implementationType, lifetime); collection.Add(descriptor); return collection; } private static IServiceCollection Add( IServiceCollection collection, Type serviceType, Func<IServiceProvider, object> implementationFactory, ServiceLifetime lifetime) { var descriptor = new ServiceDescriptor(serviceType, implementationFactory, lifetime); collection.Add(descriptor); return collection; } }
IServiceProvider扩展方法
/// <summary> /// Extension methods for getting services from an <see cref="IServiceProvider" />. /// </summary> public static class ServiceProviderServiceExtensions { /// <summary> /// Get service of type <typeparamref name="T"/> from the <see cref="IServiceProvider"/>. /// </summary> /// <typeparam name="T">The type of service object to get.</typeparam> /// <param name="provider">The <see cref="IServiceProvider"/> to retrieve the service object from.</param> /// <returns>A service object of type <typeparamref name="T"/> or null if there is no such service.</returns> public static T GetService<T>(this IServiceProvider provider) { if (provider == null) { throw new ArgumentNullException(nameof(provider)); } return (T)provider.GetService(typeof(T)); } /// <summary> /// Get service of type <paramref name="serviceType"/> from the <see cref="IServiceProvider"/>. /// </summary> /// <param name="provider">The <see cref="IServiceProvider"/> to retrieve the service object from.</param> /// <param name="serviceType">An object that specifies the type of service object to get.</param> /// <returns>A service object of type <paramref name="serviceType"/>.</returns> /// <exception cref="System.InvalidOperationException">There is no service of type <paramref name="serviceType"/>.</exception> public static object GetRequiredService(this IServiceProvider provider, Type serviceType) { if (provider == null) { throw new ArgumentNullException(nameof(provider)); } if (serviceType == null) { throw new ArgumentNullException(nameof(serviceType)); } var requiredServiceSupportingProvider = provider as ISupportRequiredService; if (requiredServiceSupportingProvider != null) { return requiredServiceSupportingProvider.GetRequiredService(serviceType); } var service = provider.GetService(serviceType); if (service == null) { throw new InvalidOperationException(Resources.FormatNoServiceRegistered(serviceType)); } return service; } /// <summary> /// Get service of type <typeparamref name="T"/> from the <see cref="IServiceProvider"/>. /// </summary> /// <typeparam name="T">The type of service object to get.</typeparam> /// <param name="provider">The <see cref="IServiceProvider"/> to retrieve the service object from.</param> /// <returns>A service object of type <typeparamref name="T"/>.</returns> /// <exception cref="System.InvalidOperationException">There is no service of type <typeparamref name="T"/>.</exception> public static T GetRequiredService<T>(this IServiceProvider provider) { if (provider == null) { throw new ArgumentNullException(nameof(provider)); } return (T)provider.GetRequiredService(typeof(T)); } /// <summary> /// Get an enumeration of services of type <typeparamref name="T"/> from the <see cref="IServiceProvider"/>. /// </summary> /// <typeparam name="T">The type of service object to get.</typeparam> /// <param name="provider">The <see cref="IServiceProvider"/> to retrieve the services from.</param> /// <returns>An enumeration of services of type <typeparamref name="T"/>.</returns> public static IEnumerable<T> GetServices<T>(this IServiceProvider provider) { if (provider == null) { throw new ArgumentNullException(nameof(provider)); } return provider.GetRequiredService<IEnumerable<T>>(); } /// <summary> /// Get an enumeration of services of type <paramref name="serviceType"/> from the <see cref="IServiceProvider"/>. /// </summary> /// <param name="provider">The <see cref="IServiceProvider"/> to retrieve the services from.</param> /// <param name="serviceType">An object that specifies the type of service object to get.</param> /// <returns>An enumeration of services of type <paramref name="serviceType"/>.</returns> public static IEnumerable<object> GetServices(this IServiceProvider provider, Type serviceType) { if (provider == null) { throw new ArgumentNullException(nameof(provider)); } if (serviceType == null) { throw new ArgumentNullException(nameof(serviceType)); } var genericEnumerable = typeof(IEnumerable<>).MakeGenericType(serviceType); return (IEnumerable<object>)provider.GetRequiredService(genericEnumerable); } /// <summary> /// Creates a new <see cref="IServiceScope"/> that can be used to resolve scoped services. /// </summary> /// <param name="provider">The <see cref="IServiceProvider"/> to create the scope from.</param> /// <returns>A <see cref="IServiceScope"/> that can be used to resolve scoped services.</returns> public static IServiceScope CreateScope(this IServiceProvider provider) { return provider.GetRequiredService<IServiceScopeFactory>().CreateScope(); } }
本文章主要分析下netcore依赖注入的几个接口和重要的类ServiceDescriptor,下篇再分析下具体的实现