WebAPI-程序集
WebAPI-程序集
在Program中,我们注册Service层和Dao层服务过于麻烦,每次添加新的Dao和Service都要注册相应的接口和实现类
可以通过程序集反射的方式,批量注册Service层和Dao层的服务
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层的程序集作为参数传入到扩展方法
builder.Services.AddServices(typeof(EmployeeService).Assembly);
builder.Services.AddDaoServices(typeof(EmployeeDaoService).Assembly);
EntityConfig
在EFCore中,我们在OnModelCreating方法中会以FluentAPI的方式配置实体类属性和数据表的关系
如果实体类过多,在DBContext文件中代码会过长的问题
在之前讲过,我们可以通过继承IEntityTypeConfiguration<>的方式来为实体类编写配置文件解决这个问题
在OnModelCreating方法中,我们仍然可以通过程序集的方式直接批量注册FluentAPI的配置文件
modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);
DbSet注册
我们需要在DbContext中注册每一个实体类,从而可以通过DbContext操作表
通过程序集反射,可以实现批量注册DbSet的操作
IEntityBase
定义一个接口,让所有的实体类实现这个接口
/// <summary>
/// 实体基类,方便程序集反射使用
/// </summary>
public interface IEntityBase
{
}
OnModelCreatingPartial
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
// 泛型方法,用于动态获取 DbSet
public DbSet<TEntity> GetDbSet<TEntity>() where TEntity : class, IEntityBase
{
return Set<TEntity>();
}
使用方法
至此,我们就实现好了DbSet的注册和获取流程,在Dao层直接通过DBContext对象调用GetDbSet()方法即可
var data = _dbContext.GetDbSet<xiaobai_cangqiong_Storage.Entity.User>().Where(u => u.Openid == openid);
// var data = _dbContext.User.Where(u => u.Openid == openid);