# 书接上文
# 上篇说到利用接口来定义生命周期
# 通过反射获取继承接口的相关实现
# 并以此来完成对应生命周期的注入
# 但随着框架搭建,已经不止业务接口层和业务实现层需要添加到 IOC 了
# 使用仓储模式后还多了仓储接口层和仓储实现层,原有的方法需要扩展
# 结构如下
- IDataService 业务接口(包含三个生命周期接口)
- DataService 业务实现
- IRepository 仓储接口(新增三个生命周期接口)
- Repository 仓储实现
# 原先的逻辑是定义三个接口在 IDataService 层下
/// <summary> | |
/// 单例 | |
/// </summary> | |
public interface ISingleton | |
{ | |
} |
/// <summary> | |
/// 瞬时 | |
/// </summary> | |
public interface ITransient | |
{ | |
} |
/// <summary> | |
/// 作用域 | |
/// </summary> | |
public interface IScoped | |
{ | |
} |
# 引用关系是不支持仓储层调用业务层的
# 所以必须在仓储接口层也重复添加这三个接口(后续可能优化)
# 扩展之后代码逻辑如下
/// <summary> | |
/// 自动注入 | |
/// </summary> | |
public static class AutoDI | |
{ | |
/// <summary> | |
/// 通过命名空间注入 | |
/// </summary> | |
/// <param name="services"></param> | |
/// <param name="namespaceType"></param> | |
/// <returns>IServiceCollection</returns> | |
public static IServiceCollection AddService(this IServiceCollection services, string namespaceType) | |
{ | |
Type? singletonType = namespaceType == nameof(IDataService) ? typeof(IDataService.DI.ISingleton) : typeof(IRepository.DI.ISingleton); | |
Type? transientType = namespaceType == nameof(IDataService) ? typeof(IDataService.DI.ITransient) : typeof(IRepository.DI.ITransient); | |
Type? scopedType = namespaceType == nameof(IDataService) ? typeof(IDataService.DI.IScoped) : typeof(IRepository.DI.IScoped); | |
if (namespaceType == nameof(IRepository)) | |
{ | |
services.AddScoped(typeof(Repository.BaseRepository<>)); | |
} | |
return AddDataServiceOrRepository(services, singletonType, transientType, scopedType); | |
} | |
/// <summary> | |
/// 注入接口和仓储类 | |
/// </summary> | |
/// <param name="services">The <see cref="IServiceCollection"/> 将服务添加到 </param> | |
/// <param name="singletonType"> 单例 </param> | |
/// <param name="transientType"> 瞬时 </param> | |
/// <param name="scopedType"> 作用域 </param> | |
/// <returns>IServiceCollection</returns> | |
public static IServiceCollection AddDataServiceOrRepository(IServiceCollection services, Type? singletonType, Type? transientType, Type? scopedType) | |
{ | |
// 获取实现了三个生命周期接口的程序集 | |
var allTypes = AppDomain.CurrentDomain.GetAssemblies() | |
.SelectMany(a => a.GetTypes().Where(t => | |
t.GetInterfaces().Contains(transientType) || | |
t.GetInterfaces().Contains(singletonType) || | |
t.GetInterfaces().Contains(scopedType))); | |
//class 的程序集 | |
var implementTypes = allTypes.Where(x => x.IsClass).ToArray(); | |
// 接口的程序集 | |
var interfaceTypes = allTypes.Where(x => x.IsInterface).ToArray(); | |
foreach (var implementType in implementTypes) | |
{ | |
var interfaceType = interfaceTypes.FirstOrDefault(x => x.IsAssignableFrom(implementType)); | |
//class 有接口,用接口注入 | |
if (interfaceType != null) | |
{ | |
// 判断用什么方式注入 | |
if (interfaceType.GetInterfaces().Contains(singletonType)) | |
{ | |
// 单例 | |
services.AddSingleton(interfaceType, implementType); | |
} | |
else if (interfaceType.GetInterfaces().Contains(transientType)) | |
{ | |
// 瞬时 | |
services.AddTransient(interfaceType, implementType); | |
} | |
else if (interfaceType.GetInterfaces().Contains(scopedType)) | |
{ | |
// 作用域 | |
services.AddScoped(interfaceType, implementType); | |
} | |
} | |
else //class 没有接口,直接注入 class | |
{ | |
// 判断用什么方式注入 | |
if (implementType.GetInterfaces().Contains(singletonType)) | |
{ | |
// 单例 | |
services.AddSingleton(implementType); | |
} | |
else if (implementType.GetInterfaces().Contains(transientType)) | |
{ | |
// 瞬时 | |
services.AddTransient(implementType); | |
} | |
else if (implementType.GetInterfaces().Contains(scopedType)) | |
{ | |
// 作用域 | |
services.AddScoped(implementType); | |
} | |
} | |
} | |
return services; | |
} | |
} |
# Program 注册服务
var builder = WebApplication.CreateBuilder(args); | |
// 自动注入接口实现类和仓储实现类 | |
builder.Services.AddService(nameof(IDataService)); | |
builder.Services.AddService(nameof(IRepository)); |
# 需要调用两次并且传入不同命名空间
# 而且代码逻辑有点混乱不是很好阅读
# 优化一下
/// <summary> | |
/// 自动注入 | |
/// </summary> | |
public static class AutoDI | |
{ | |
/// <summary> | |
/// 通过命名空间注入 | |
/// </summary> | |
/// <param name="services"></param> | |
/// <param name="namespaceType"></param> | |
public static void AddService(this IServiceCollection services, string namespaceType) | |
{ | |
Type singletonType = null; | |
Type transientType = null; | |
Type scopedType = null; | |
switch (namespaceType) | |
{ | |
case nameof(IDataService): | |
singletonType = typeof(IDataService.DI.ISingleton); | |
transientType = typeof(IDataService.DI.ITransient); | |
scopedType = typeof(IDataService.DI.IScoped); | |
break; | |
case nameof(IRepository): | |
singletonType = typeof(IRepository.DI.ISingleton); | |
transientType = typeof(IRepository.DI.ITransient); | |
scopedType = typeof(IRepository.DI.IScoped); | |
services.AddScoped(typeof(Repository.BaseRepository<>)); | |
break; | |
default: | |
break; | |
} | |
services.AddDataServiceOrRepository(singletonType, transientType, scopedType); | |
} | |
/// <summary> | |
/// 注入接口和仓储类 | |
/// </summary> | |
/// <param name="services">The <see cref="IServiceCollection"/> 将服务添加到 </param> | |
/// <param name="singletonType"> 单例 </param> | |
/// <param name="transientType"> 瞬时 </param> | |
/// <param name="scopedType"> 作用域 </param> | |
public static void AddDataServiceOrRepository(this IServiceCollection services, Type? singletonType, Type? transientType, Type? scopedType) | |
{ | |
// 获取实现了三个生命周期接口的程序集 | |
var allTypes = AppDomain.CurrentDomain.GetAssemblies() | |
.SelectMany(a => a.GetTypes().Where(t => | |
t.GetInterfaces().Contains(singletonType) || | |
t.GetInterfaces().Contains(transientType) || | |
t.GetInterfaces().Contains(scopedType))); | |
// 实现类的程序集 | |
var implementationTypes = allTypes.Where(x => x.IsClass).ToArray(); | |
// 服务接口的程序集 | |
var serviceTypes = allTypes.Where(x => x.IsInterface).ToArray(); | |
foreach (var implementationType in implementationTypes) | |
{ | |
var serviceType = serviceTypes.FirstOrDefault(x => x.IsAssignableFrom(implementationType)); | |
if (implementationType.GetInterfaces().Contains(singletonType)) | |
{ | |
// 单例 | |
services.AddFromLifeTime(serviceType, implementationType, ServiceLifetime.Singleton); | |
} | |
else if (implementationType.GetInterfaces().Contains(transientType)) | |
{ | |
// 瞬时 | |
services.AddFromLifeTime(serviceType, implementationType, ServiceLifetime.Transient); | |
} | |
else if (implementationType.GetInterfaces().Contains(scopedType)) | |
{ | |
// 作用域 | |
services.AddFromLifeTime(serviceType, implementationType, ServiceLifetime.Scoped); | |
} | |
} | |
} | |
/// <summary> | |
/// 通过生命周期注入接口和实现类 | |
/// </summary> | |
/// <param name="services">The <see cref="IServiceCollection"/> 将服务添加到 </param> | |
/// <param name="serviceType"> 要注册的服务类型(Interface)</param> | |
/// <param name="implementationType"> 服务的实现类型(Class)</param> | |
/// <param name="lifetime"> 注入生命周期 </param> | |
/// <exception cref="ArgumentOutOfRangeException"></exception> | |
/// <returns>IServiceCollection</returns> | |
public static IServiceCollection AddFromLifeTime(this IServiceCollection services, Type serviceType, Type implementationType, ServiceLifetime lifetime) | |
{ | |
switch (lifetime) | |
{ | |
// 单例 | |
case ServiceLifetime.Singleton: | |
services.AddSingleton(serviceType ?? implementationType, implementationType); | |
break; | |
// 瞬时 | |
case ServiceLifetime.Transient: | |
services.AddTransient(serviceType ?? implementationType, implementationType); | |
break; | |
// 作用域 | |
case ServiceLifetime.Scoped: | |
services.AddScoped(serviceType ?? implementationType, implementationType); | |
break; | |
default: | |
throw new ArgumentOutOfRangeException(nameof(lifetime), lifetime, null); | |
} | |
return services; | |
} | |
} |