WebAPI-程序集

WebAPI-程序集

在Program中,我们注册Service层和Dao层服务过于麻烦,每次添加新的Dao和Service都要注册相应的接口和实现类

可以通过程序集反射的方式,批量注册Service层和Dao层的服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
public static class ServiceCollectionExtensions
{
/// <summary>
/// 自动注册服务层中的所有服务。
/// </summary>
/// <param name="services">服务集合。</param>
/// <param name="assembly">包含服务类的程序集。</param>
/// <returns>配置后的服务集合。</returns>
public static IServiceCollection AddServices(this IServiceCollection services, Assembly assembly)
{
// 获取程序集中的所有命名空间
var namespaces = GetNamespaces(assembly);

// 遍历每个命名空间
foreach (var namespaceName in namespaces)
{
// 获取当前命名空间下的所有类型
var typesInNamespace = assembly.GetTypes()
.Where(type => type.Namespace == namespaceName);

// 遍历每个类型
foreach (var type in typesInNamespace)
{
// 查找类型实现的接口
var interfaceType = type.GetInterfaces()
.FirstOrDefault(i => i.Name == $"I{type.Name}");

// 如果找到了匹配的接口
if (interfaceType != null)
{
// 将接口和实现类注册为 scoped 服务
services.AddScoped(interfaceType, type);
}
}
}

return services;
}

/// <summary>
/// 自动注册 DAO 层中的所有服务。
/// </summary>
/// <param name="services">服务集合。</param>
/// <param name="assembly">包含 DAO 类的程序集。</param>
/// <returns>配置后的服务集合。</returns>
public static IServiceCollection AddDaoServices(this IServiceCollection services, Assembly assembly)
{
// 获取程序集中的所有命名空间
var namespaces = GetNamespaces(assembly);

// 遍历每个命名空间
foreach (var namespaceName in namespaces)
{
// 获取当前命名空间下的所有类型
var typesInNamespace = assembly.GetTypes()
.Where(type => type.Namespace == namespaceName);

// 遍历每个类型
foreach (var type in typesInNamespace)
{
// 查找类型实现的接口
var interfaceType = type.GetInterfaces()
.FirstOrDefault(i => i.Name == $"I{type.Name}");

// 如果找到了匹配的接口
if (interfaceType != null)
{
// 将接口和实现类注册为 scoped 服务
services.AddScoped(interfaceType, type);
}
}
}

return services;
}

/// <summary>
/// 获取程序集中的所有命名空间。
/// </summary>
/// <param name="assembly">要检查的程序集。</param>
/// <returns>包含所有命名空间的集合。</returns>
private static IEnumerable<string> GetNamespaces(Assembly assembly)
{
var namespaces = new HashSet<string>();

// 遍历程序集中的所有类型
foreach (var type in assembly.GetTypes())
{
// 添加类型所属的命名空间
namespaces.Add(type.Namespace);
}

return namespaces;
}
}

Program.cs

将Service层和Dao层的程序集作为参数传入到扩展方法

1
2
builder.Services.AddServices(typeof(EmployeeService).Assembly);
builder.Services.AddDaoServices(typeof(EmployeeDaoService).Assembly);

EntityConfig

在EFCore中,我们在OnModelCreating方法中会以FluentAPI的方式配置实体类属性和数据表的关系

如果实体类过多,在DBContext文件中代码会过长的问题

在之前讲过,我们可以通过继承IEntityTypeConfiguration<>的方式来为实体类编写配置文件解决这个问题

在OnModelCreating方法中,我们仍然可以通过程序集的方式直接批量注册FluentAPI的配置文件

1
modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);

DbSet注册

我们需要在DbContext中注册每一个实体类,从而可以通过DbContext操作表

通过程序集反射,可以实现批量注册DbSet的操作

IEntityBase

定义一个接口,让所有的实体类实现这个接口

1
2
3
4
5
6
/// <summary>
/// 实体基类,方便程序集反射使用
/// </summary>
public interface IEntityBase
{
}
OnModelCreatingPartial
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void OnModelCreatingPartial(ModelBuilder modelBuilder)
{
// 获取当前程序集
var assembly = Assembly.GetExecutingAssembly();

// 查找所有实现了 IEntity 接口的类型
var entityTypes = assembly.GetTypes()
.Where(t => t.IsClass && !t.IsAbstract && typeof(IEntityBase).IsAssignableFrom(t));

foreach (var entityType in entityTypes)
{
// 注册 DbSet
modelBuilder.Entity(entityType);
}
}
GetDbSet
1
2
3
4
5
// 泛型方法,用于动态获取 DbSet
public DbSet<TEntity> GetDbSet<TEntity>() where TEntity : class, IEntityBase
{
return Set<TEntity>();
}
使用方法

至此,我们就实现好了DbSet的注册和获取流程,在Dao层直接通过DBContext对象调用GetDbSet()方法即可

1
2
var data = _dbContext.GetDbSet<xiaobai_cangqiong_Storage.Entity.User>().Where(u => u.Openid == openid);
// var data = _dbContext.User.Where(u => u.Openid == openid);


WebAPI-程序集
http://blog.170827.xyz/2024/11/16/WebAPI-程序集/
作者
XIAOBAI
发布于
2024年11月16日
许可协议